【问题标题】:Why would the compiler link to the wrong method when MS Release library is used?为什么使用 MS Release 库时编译器会链接到错误的方法?
【发布时间】:2021-04-06 10:45:36
【问题描述】:

程序在发布模式下链接到错误的方法。我有使用 VS2019 WIN32 构建的 9 个项目的 C++ 解决方案。它在 Debug 构建中运行良好,但在 Release 中构建时失败并出现错误: 运行时检查失败 #0 - ESP 的值未在函数调用中正确保存。 从不是我的 dll 中的方法调用返回时会发生这种情况。

我做了一个新配置,它是 Debug 版本的副本。它运行得很好。 然后,我将所有 9 个项目中的预处理器定义从 _DEBUG 更改为 NDEBUG,并重建了解决方案。它运行得很好。 然后,我在所有 9 个项目中将运行时库从“多线程调试 DLL (/MDd)”更改为“多线程 DLL (/MD)”,并重建了解决方案(需要一个小时的大部分时间)。这次我在运行时得到了上面显示的堆栈错误。

跟踪反汇编,我发现 /MD 版本以 3 个指针作为参数调用预期的方法,但它执行的方法只有一个参数,因此清理在堆栈上留下 8 个字节,产生错误。 根据包含文件,所需的方法是一个相当大的类中的虚函数。在遇到错误方法之前,该类在运行时有几个成功的方法调用。 为了验证,我将所有 9 个运行时库都改回了 /MDd,重新构建,得到了一个正在运行的程序。

在所有预处理器定义相同的情况下,库版本链接有何不同?

【问题讨论】:

  • 我会设置一个空白项目来仅链接该 dll 并调用有问题的方法以查看问题是否重复。我认为链接器与 dll 没有任何关系,因为链接是在加载时或运行时动态发生的,GetProcAddress
  • 澄清一下。这是一个简单的方法调用。没有模板,没有 vtable 操作,只是一个 class->method(ptr,ptr,ptr)。深入研究包含文件,被执行的方法在从主程序调用虚函数之前直接声明为虚函数。除了运行时库没有任何改变。包含文件、dll 的库和 dll 都完全相同。什么可以使链接器将调用移动 4 个字节?
  • MatG:如果我花钱在一个较小的程序中复制这个/或不复制,那会告诉我什么?
  • 如果问题再次出现,您可以发布一个更小更简单的项目;如果问题没有重复,您可以缩小原因并分析两个项目之间的差异。您继续谈论链接器,但它与 DLL 库无关:绑定发生在您运行程序时。

标签: windows visual-studio visual-c++ linker


【解决方案1】:

解决方案是获取动态链接库的发布版本。显然供应商发布了一个调试版本。 MS 必须在 Debug 中链接额外的东西,使偏移量在 Release 模式下上移一个指针。

【讨论】:

    猜你喜欢
    • 2018-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 2012-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多