希望更深入地了解Visual Studio C-runtime库链接行为

时间:2012-04-04 15:46:58

标签: c visual-studio static-linking msvcrt

这是我盲目接受并遵循的“它的方式”。我正在努力深入了解背后的“原因”。

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

很好地记录了here以及传递给链接器的给定调用的所有模块必须使用相同的运行时库编译器选项编译的许多其他地方。

如果在讨论herehere的应用的最终链接期间执行了所有符号解析,为什么会出现这种情况?为什么LibA和LibB甚至需要指定一个特定的运行时库来构建时使用?不应该使用C运行时调用它们只针对App为其链接指定的运行时间进行解析吗?

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

1 个答案:

答案 0 :(得分:0)

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

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

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

多线程与单线程:
这两种运行时类型之间的冲突可能是显而易见的。单线程版本不是线程安全的,因此将其与预期线程安全性的东西混合将在以后进行有趣的调试。这种区别主要仅存在于较旧的MS编译器中,因为在新版本中唯一的选项是多线程。

另请参阅此类似问题:Mixing Static Libraries of C Code built from different versions of Visual Studio 2002 and later