我继承了一个非常大而复杂的项目(实际上是一个'解决方案',包含119个'项目',其中大多数是DLL),它是在VC8(VS2005)下构建和测试的,我的任务是移植它到VC9(VS2008)。
我使用的移植过程是:
到目前为止,我在最后一步遇到了以下问题。
1)计算装饰名称的方式发生变化,导致名称截断。
这不仅仅是一个警告(http://msdn.microsoft.com/en-us/library/074af4b6.aspx)。使用此警告构建的库不会与其他模块链接。应用MSDN中给出的解决方案并非易事,但可行。我在How do I increase the allowed decorated name length in VC9 (MSVC 2008)?
中单独解决了这个问题2)不允许将零赋值给迭代器的更改。这是根据规范,并且很容易找到并修复这些先前允许的编码错误。不要将零赋值给迭代器,而是使用值end()。
3)for循环范围现在符合ANSI标准。另一个容易解决的问题。
4)预编译头文件需要更多空间。在某些情况下,需要更多的空间。我最终使用/ Zm999来提供最大的PCH空间。如果PCH内存使用率再次上升,我认为我将不得不完全放弃PCH,并且只是承受已经很长的构建时间的增加。
5)复制ctors和默认dtors的要求发生变化。看来在模板类中,在某些我还没有想到的条件下,编译器不再生成默认的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似乎混淆了小对象分配器,从而导致一些虚假的诊断。该程序的操作似乎没有受到实质性影响,但质量保证人员不允许虚假诊断通过它们。
有没有办法在加载DLL之前强制构建全局对象?
我可能会遇到哪些其他移植问题?
答案 0 :(得分:1)
有没有办法在加载DLL之前强制构建全局对象?
DELAYLOAD选项怎么样?那么DLL在第一次调用之前不会加载吗?
答案 1 :(得分:1)
这是一个棘手的问题,主要是因为你继承了一个本身就很危险的设计,因为你不应该依赖全局变量的初始化顺序。
这听起来像你可以通过调用一个返回指向单例对象的指针的全局函数或方法来替换其他函数检索的单例来尝试解决全局变量。如果在调用时对象存在,则该函数返回指向它的指针。否则,它分配一个新的并返回指向新分配的对象的指针。
当然,问题在于我无法想到一个可以避免你所描述的问题的单例实现。也许这个讨论很有用:http://www.oneunified.net/blog/Personal/SoftwareDevelopment/CPP/Singleton.article
答案 2 :(得分:0)
这肯定是一个有趣的问题。除了改变设计之外,我没有其他解决方案,因此不依赖于订单或链接/ dll启动的未定义行为。您是否考虑过与旧链接器链接? (或任何VS.NET术语)
因为变量和分配器的行为依赖于某些(当时未知)任意启动顺序,我可能会修复它,以便将来不会出现问题。我想你真的在问是否有人知道如何在VC9中做一些伏都教来使问题消失。我也有兴趣听听它。
答案 3 :(得分:0)
这个怎么样,
答案 4 :(得分:0)
问题的解决方案比我原先想象的要简单得多。初始化顺序问题是由于存在从std容器类型派生的几个类型的全局变量(一个基本的设计缺陷,早于我在该公司的位置)引起的。解决方案是用单身替换所有这些全局变量。大约有100个。
完成此操作后,初始化(和销毁)命令由程序员控制。