2

这是我只是盲目地接受并遵循“它的方式”的东西。我试图更深入地了解其背后的“原因”。

  • 静态库 LibA - 使用一些 C 运行时调用
  • 静态库 LibB - 利用一些 C 运行时调用
  • 可执行应用程序 - 利用 LibA、LibB 和一些 C 运行时调用

这里有很好的记录,还有很多其他地方,所有传递给链接器的给定调用的模块都必须使用相同的运行时库编译器选项进行编译。

如果所有符号解析都是在此处此处讨论的 App 的最终链接期间执行的,为什么会出现这种情况?为什么 LibA 和 LibB 在构建时甚至需要指定要使用的特定运行时库?他们使用的 C 运行时调用不应该只解决 App 为其链接指定的任何运行时调用吗?

这是其他 C 开发环境中的问题还是 Visual Studio 特有的问题?

4

1 回答 1

0

正如 Hans Passant 在他的评论中提到的,有一些全局状态项必须在 DLL 运行时和静态链接运行时之间进行更改。比他的示例更糟糕的是,类型的大小根据创建它的运行时而改变。但是,还有几个原因:

调试与发布:
调试运行时将在动态分配的内存周围放置保护字节。这允许他们的内存分配和释放代码进行额外检查,以帮助您发现内存问题,例如双重释放和在分配的缓冲区之外写入。发布运行时不使用额外的检查来支持优化。因此,如果内存分配给一个并释放另一个,您可能会得到不可预知的结果。

DLL 与静态链接:
在 Windows 中,经验法则是您必须在分配它的同一模块中释放内存。换句话说,如果您在 msvcrt.dll 中分配了内存,您还必须在那里释放它。因此,如果应用程序的某些部分链接到静态运行时,而某些部分链接到运行时 DLL,则可能违反此规则。发生这种情况时,您还会得到不可预测的结果,包括异常。

多线程与单线程:
这两种运行时类型之间潜在的冲突应该是显而易见的。单线程版本不是线程安全的,因此将它与期望线程安全的东西混合起来会在以后进行有趣的调试。这种区别主要只存在于较旧的 MS 编译器中,因为在较新的版本中唯一的选择是多线程的。

另请参阅此类似问题:混合从不同版本的 Visual Studio 2002 和更高版本构建的 C 代码的静态库

于 2012-05-12T01:24:22.153 回答