“/MD /MT”和“dll lib”之间的概念歧义

Posted

技术标签:

【中文标题】“/MD /MT”和“dll lib”之间的概念歧义【英文标题】:Conceptual ambiguity between "/MD /MT " and "dll lib" 【发布时间】:2016-03-09 06:10:51 【问题描述】:

我对 Windows 上运行时库选项之间的概念感到困惑。我以为我知道lib和dll之间的区别。 lib 将被编译为您的代码,dll 将在执行时动态加载。但是当我编译一个库时,我不得不在/MD/MT 之间做出选择。在 msdn.microsoft.com 上据说:

使用 /MD 编译的应用程序静态链接到 MSVCRT.lib。 该库提供了一层代码,使链接器能够 解决外部引用。实际工作代码包含在 MSVCRversionnumber.DLL,它必须在运行时可用 与 MSVCRT.lib 链接的应用程序。

此时我无法理解当我使用 lib 时还需要动态加载 dll。似乎使用/MD 选项构建lib 将导致“动态库”,或者使用/MT 选项构建dll 将导致“静态dll”。

那么“/MD vs /MT”和“lib vs dll”有什么区别?

【问题讨论】:

/MT 仅适用于创建不使用任何模块的程序时。它唯一的优点是程序很容易部署到另一台机器上,只需复制一个 EXE 文件。当您在使用 DLL 的设备中使用它时,您已经失去了这一优势。并且必须处理进程具有多个 C 运行时副本的事实。这是一个非常非常冒险的提议,CRT 有很多全局状态。像errno 这样基本的东西不能正常工作。千万不要那样做,就这么简单。 【参考方案1】:

其中一个关键方面是区分构建/编译时问题和运行时问题。

在构建时,编译器和链接器需要关于如何编译和构建代码的足够信息;数据定义、函数位置等。头文件为编译器提供了大部分详细信息,链接器需要能够定位函数1 以完成该过程。

如果 dll 也提供了一个 lib(如 /MD 的情况),此 lib 包含链接器查找所需函数所需的最少代码和一些在运行时加载 dll 的附加代码。可以制作一个不与 lib 链接的程序(即使有 dll),然后您需要在运行时加载 dll(通过LoadLibrary)并修复指针(通过GetProcAddress)到您需要调用的函数1。 C++ 库比较困难,因此通常不会尝试,名称修饰会使这变得更难(使用 C 库通常要容易得多)。

如果该库是一个没有关联 dll 的静态库(对于运行时,这是/MT),则该库包含运行和执行其给定功能所需的所有代码。链接器将所有需要的代码链接到目标中,不需要额外的运行时加载。

1我在这里松散地使用函数这个词,但它也包括所有外部。

【讨论】:

非常感谢。您的回复以及 JasonB 的回复清楚地解释了这个问题的细节。现在我已经成功编译了程序,并意识到我选择这些构建选项背后发生了什么。您肯定是这方面的专家。 @Niall:谢谢,使用LoadLibrary 技巧从第二个 MT 构建库调用 MD 构建库是否可行? @Rika。在概念上可能/可能。但这对我来说对运行时库没有太大意义,只需使用您想要的版本即可。 非常感谢,非常感谢。这背后的原因是,Pytorch 的 C++ 库(libtorch)不支持 MTd 构建,这就是我问这个问题的原因,因为我想不出任何其他方法来规避这个问题。 @Rika。如果库不公开任何 C++ 运行时类型,或管理您分配的内存,反之亦然,您应该没问题。【参考方案2】:

在这两种情况下,应用程序都将与.lib 文件静态链接,但如果使用/MT,则它将与包含C 运行的libcmt.liblibcmtd.lib(发布/调试)链接-time 本身,而如果使用/MD,它将与msvcrt.libmsvcrtd.lib 链接,它们只是DLL 的导入库,不包含运行时。

详情请见https://msdn.microsoft.com/en-us/library/abx4dbyh(v=vs.120).aspx。

(请注意,在 VS2015 中,库已拆分并具有新名称;C99 部分名称分别为 libucrt.liblibucrtd.libucrt.libucrtd.lib。)

【讨论】:

哦,谢谢。我看到了。所以即使是一个lib也只能静态链接到一个程序,但是使用/MD选项,我们使用的lib,它本身就依赖于相应的dll文件。 导入库文件用于加载时动态链接;它使您可以更轻松地使用 DLL,而无需为您要使用的每个函数调用 LoadLibrary()GetProcAddress()。如果您不想要加载时动态链接(例如,如果 DLL 可用,您的程序将使用 DLL,但如果没有,则在没有它的情况下继续存在),那么您必须在上述调用中使用运行时动态链接。详情请见MSDN。【参考方案3】:

每个DLL 也有一个对应的.lib 文件。链接器链接到.lib 文件,该文件具有指示在运行时需要从DLL 加载哪些符号的必要指令。

【讨论】:

感谢您的回复。但是如果每个dll都有对应的.lib文件,那我自己编译的dll的.lib文件在哪里呢?还是这条规则只适用于 c 运行时 dll?

以上是关于“/MD /MT”和“dll lib”之间的概念歧义的主要内容,如果未能解决你的问题,请参考以下文章

SACC2017听 ChinaUnix 资深版主刘歧畅谈 SACC 2017

VC运行时库(/MD/MT等)

一文带你弄懂Visual Studio:运行时库及MT/MTDMD/MDD

部分专业化消歧优先链的更好模式?

NLP第十篇-语义分析

DLL和LIB文件都是干啥用的?怎么用在VC++里面?