我继承了一个在 VC8(VS2005)下构建和测试的非常庞大而复杂的项目(实际上是一个由 119 个“项目”组成的“解决方案”,其中大部分是 DLL),我的任务是将它移植到 VC9 (VS2008)。
我使用的移植过程是:
- 复制 VC8 .sln 文件并将其重命名为 VC9 .sln 文件。
- 复制所有 VC8 项目文件,并将它们重命名为 VC9 项目文件。
- 编辑所有 VC9 项目文件,s/vc8/vc9。
- 编辑 VC9 .sln, s/vc8/vc9/
- 使用 VS2008 加载 VC9 .sln,并让 IDE“转换”所有项目文件。
- 修复编译器和链接器错误,直到我得到一个好的构建。
到目前为止,我在最后一步中遇到了以下问题。
1) 修饰名称的计算方式发生变化,导致名称被截断。
这不仅仅是一个警告 ( http://msdn.microsoft.com/en-us/library/074af4b6.aspx )。使用此警告构建的库不会与其他模块链接。应用 MSDN 中给出的解决方案并非易事,而是可行的。我在如何增加 VC9 (MSVC 2008) 中允许的修饰名称长度?
2) 不允许将零分配给迭代器的更改。这是符合规范的,很容易找到并修复这些以前允许的编码错误。不要将零分配给迭代器,而是使用值 end()。
3) for-loop 范围现在符合 ANSI 标准。另一个容易解决的问题。
4) 预编译头文件需要更多空间。在某些情况下,需要更多的空间。我最终使用 /Zm999 来提供最大的 PCH 空间。如果 PCH 内存使用量再次增加,我认为我将不得不完全放弃 PCH,并忍受已经很长的构建时间的增加。
5) 对复制 ctor 和默认 dtor 的要求有所改变。似乎在模板类中,在我还没有完全弄清楚的某些条件下,编译器不再生成默认 ctor 或默认 dtor。我怀疑这是 VC9 中的一个错误,但可能还有其他我做错的事情。如果是这样,我肯定想知道它是什么。
6) sln 和 vcproj 文件中的 GUID 没有改变。这似乎不会以我可以检测到的任何方式影响构建,但仍然令人担忧。
请注意,尽管存在所有这些问题,该项目还是在 VC8 下构建、运行并通过了广泛的 QA 测试。我还将所有更改移植到 VC8 项目中,它们仍然像以前一样愉快地构建和运行(使用 VS2005/VC8)。因此,我为 VC9 构建所需的所有更改至少看起来是向后兼容的,尽管回归测试仍在进行中。
现在解决真正困难的问题:我遇到了 VC8 和 VC9 项目的启动顺序不同。该程序使用了一个仿照 Loki 的小对象分配器,在 Andrei Alexandrescu 的 Book Modern C++ Design中。该分配器使用主程序模块中定义的全局变量进行初始化。
在 VC8 下,这个全局变量是在程序启动的最开始时从模块 crtexe.c 中的代码构造的。在VC9下,第一个执行的模块是crtdll.c,表示启动顺序发生了变化。正在启动的 DLL 似乎通过在全局对象初始化统计信息之前分配和取消分配内存来混淆小对象分配器,这会导致一些虚假的诊断。该程序的运行似乎没有受到实质性影响,但 QA 人员不会允许虚假诊断通过他们。
有没有办法在加载 DLL 之前强制构建全局对象?
我可能会遇到哪些其他移植问题?