从VC8(VS2005)迁移到VC9(VS2008)有哪些移植问题?

3
我继承了一个非常庞大且复杂的项目(实际上是由119个“项目”组成的“解决方案”,其中大多数是DLL),该项目在VC8(VS2005)下构建和测试,我需要将其移植到VC9(VS2008)。
我使用的移植过程如下:
1. 复制VC8 .sln文件并将其重命名为VC9 .sln文件。 2. 复制所有VC8项目文件,并将它们重命名为VC9项目文件。 3. 编辑所有VC9项目文件,将vc8替换为vc9。 4. 编辑VC9 .sln文件,将vc8替换为vc9。 5. 使用VS2008加载VC9 .sln文件,并让IDE“转换”所有项目文件。 6. 修复编译器和链接器错误,直到获得良好的构建。
到目前为止,在最后一步中我遇到了以下问题:
1. 改变了装饰名称计算的方式,导致名称被截断。这不仅仅是一个警告,(http://msdn.microsoft.com/en-us/library/074af4b6.aspx)。使用此警告构建的库将无法与其他模块链接。应用MSDN中给出的解决方案很困难,但可行。我在这里单独解决了这个问题。
2. 更改不允许将零分配给迭代器。这是根据规范,以前允许的编码错误很容易找到和修复。使用end()值代替向迭代器赋值为零。
3. for循环作用域现在符合ANSI标准。一个易于解决的问题。
4. 预编译头需要更多空间。在某些情况下,需要更多的空间。我最终使用/Zm999提供最大的PCH空间。如果PCH内存使用率再次增加,我认为我将不得不放弃PCH,只需忍受已经非常长的构建时间的增加。
5. 复制构造函数和默认析构函数的要求发生了变化。在模板类中,似乎在某些条件下编译器不再生成默认构造函数或默认析构函数。我怀疑这是VC9中的一个错误,但可能还有其他我做错了的事情。如果是这样,请告诉我具体是什么。

6) sln和vcproj文件中的GUID没有更改。据我所知,这似乎并不会对构建产生影响,但仍然令人担忧。

需要注意的是,尽管存在所有这些问题,该项目在VC8下构建、运行并通过了广泛的QA测试。我还将所有更改回溯到了VC8项目中,在那里它们仍然像以前一样愉快地构建和运行(使用VS2005 / VC8)。因此,我为VC9构建所需的所有更改至少看起来是向后兼容的,尽管回归测试仍在进行中。

现在是真正困难的问题:我遇到了VC8和VC9项目之间启动顺序的差异。程序使用一个类似于Loki的小对象分配器,模仿Andrei Alexandrescu的书《现代C++设计》。该分配器使用在主程序模块中定义的全局变量进行初始化。

在VC8下,此全局变量在程序启动的最开始从crtexe.c模块中的代码中构造。在VC9下,执行的第一个模块是crtdll.c,这表明启动顺序已更改。正在启动的DLL似乎通过在全局对象可以初始化统计信息之前分配和释放内存来混淆小对象分配器,这导致了一些虚假诊断。程序的操作似乎没有受到实质性影响,但QA人员不会允许虚假诊断通过。

是否有一种方法可以在加载DLL之前强制构造全局对象?

我可能会遇到哪些其他移植问题?

5个回答

1
有没有一种方法可以在加载DLL之前强制构建全局对象?
延迟加载选项怎么样?这样DLL直到第一次调用才会被加载?

1

这是一个棘手的问题,主要是因为你继承了一个本质上危险的设计,因为你不应该依赖全局变量的初始化顺序。

听起来你可以尝试通过用单例替换全局变量来解决这个问题,其他函数通过调用返回指向单例对象的全局函数或方法来检索它。如果对象在调用时存在,则函数返回指向它的指针。否则,它会分配一个新的并返回指向新分配的对象的指针。

当然,问题在于我想不出一个单例实现能避免你描述的问题。也许这个讨论会有用:http://www.oneunified.net/blog/Personal/SoftwareDevelopment/CPP/Singleton.article


结果证明使用单例是最好的答案。谢谢! - Howard Lee Harkness

0

这样怎么样?

  1. 将您的主程序也制作成 DLL,称为 main.dll,并链接到所有其他 DLL,并将主函数导出为 mainEntry()。删除全局变量。
  2. 创建一个新的主 exe,其中包含全局变量及其初始化,但不会静态链接到任何其他应用程序 DLL(除了分配器内容)。
  3. 然后,这个新的 main.exe 使用 LoadLibrary() 动态加载 main.dll,然后使用 GetProcAddress 调用 mainEntry()。

0

这确实是一个有趣的问题。除了改变设计以消除对链接/ dll 启动顺序未定义行为的依赖之外,我没有其他解决方案。您考虑过使用旧的链接器进行链接吗?(或者使用 VS.NET 的术语)

因为您的变量和分配器的行为依赖于一些(当时未知的)任意启动顺序,所以我可能会修复它,以便将来不会出现问题。我猜您真正想知道是否有人知道如何在 VC9 中做一些巫术来解决这个问题。我也很感兴趣听到这个。


0
问题的解决方案比我最初想象的要直接得多。初始化顺序问题是由于存在几个派生自std容器类型的全局变量(这是一种基本的设计缺陷,早在我加入该公司之前就存在了)所致。解决方案是用单例替换所有这样的全局变量。大约有100个。
一旦完成了这个操作,初始化(和销毁)顺序就在程序员的控制下了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接