【问题标题】:What are the porting issues going from VC8 (VS2005) to VC9 (VS2008)?从 VC8 (VS2005) 到 VC9 (VS2008) 的移植问题是什么?
【发布时间】:2008-10-31 16:11:11
【问题描述】:

我继承了一个在VC8(VS2005)下构建和测试的非常庞大和复杂的项目(实际上是一个由119个“项目”组成的“解决方案”,其中大部分是DLL),我的任务是移植它到 VC9 (VS2008)。

我使用的移植过程是:

  1. 复制 VC8 .sln 文件并重命名 到 VC9 .sln 文件。
  2. 复制所有 VC8项目文件,并重命名 将它们添加到 VC9 项目文件中。
  3. 编辑 所有 VC9 项目文件, s/vc8/vc9。
  4. 编辑 VC9 .sln, s/vc8/vc9/
  5. 加载 VC9 .sln VS2008,让IDE“转换” 所有项目文件。
  6. 修复 编译器和链接器错误,直到我 构建良好。

到目前为止,我在最后一步中遇到了以下问题。

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) 对复制 ctor 和默认 dtor 的要求进行了更改。似乎在模板类中,在我还没有完全弄清楚的某些条件下,编译器不再生成默认 ctor 或默认 dtor。我怀疑这是 VC9 中的一个错误,但可能还有其他我做错的事情。如果是这样,我肯定想知道它是什么。

6) sln 和 vcproj 文件中的 GUID 未更改。这似乎不会以任何我可以检测到的方式影响构建,但仍然令人担忧。

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

现在解决真正棘手的问题:我遇到了 VC8 和 VC9 项目的启动顺序不同。该程序使用了一个仿照 Loki 的小对象分配器,在 Andrei Alexandrescu 的Modern C++ Design一书中。该分配器使用主程序模块中定义的全局变量进行初始化。

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

有没有办法在加载 DLL 之前强制构建一个全局对象?

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

【问题讨论】:

    标签: visual-c++ visual-c++-2008 name-decoration vc8


    【解决方案1】:

    有没有办法在加载 DLL 之前强制构建一个全局对象?

    DELAYLOAD 选项怎么样?这样 DLL 在第一次调用之前不会加载?

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

      • 原来使用单例是最好的答案。谢谢!
      【解决方案3】:

      这当然是一个有趣的问题。除了改变设计以便不依赖于未定义的订单行为或链接/dll 启动之外,我没有其他解决方案。您是否考虑过使用旧链接器进行链接? (或任何 VS.NET 术语)

      因为你的变量和分配器的行为依赖于一些(当时未知的)任意启动顺序,我可能会解决这个问题,这样将来就不会出现问题了。我想你真的在问是否有人知道如何在 VC9 中做一些巫术来使问题消失。我也有兴趣听听。

      【讨论】:

        【解决方案4】:

        这个怎么样,

        1. 将主程序也设为 DLL,将其命名为 main.dll,链接到所有其他程序,然后将主函数导出为 mainEntry()。删除全局变量。
        2. 创建一个新的主 exe,它具有全局变量及其初始化,但不静态链接到任何其他应用程序 DLL(分配器除外)。
        3. 这个新的 main.exe 然后使用 LoadLibrary() 动态加载 main.dll,然后使用 GetProcAddress 调用 mainEntry()。

        【讨论】:

          【解决方案5】:

          问题的解决方案比我最初想象的要简单。初始化顺序问题是由于存在几个从标准容器类型派生的类型的全局变量(在我在该公司任职之前的基本设计缺陷)。解决方案是用单例替换所有这些全局变量。大约有 100 个。

          一旦完成,初始化(和销毁)顺序就在程序员的控制之下。

          【讨论】:

            猜你喜欢
            • 2014-07-31
            • 1970-01-01
            • 1970-01-01
            • 2010-09-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-17
            • 2011-07-03
            相关资源
            最近更新 更多