2014-06-17 58 views
0

我有一个使用3-4个外部库的C文件。它使用cl.exelink.exe(MSVC)构建。使用/ c和/ MD选项编译C文件,然后链接.lib文件

构建脚本显示生成exe文件的过程有两个滑台

  • 使用与cl.exe的“/ C”选项,以获得.o文件。其他一些标志也给出了这个,但我关心的是/MD。 MSDN说:

导致使用运行时库的多线程特异性和DLL版本的应用程序。定义_MT和_DLL并使编译器将库名称MSVCRT.lib放入.obj文件中。

什么用的给/MDcl当我们只编译,而不是链接?

  • 在此之后,link.exe用于生成exe。几个.lib文件被指定为链接(如ole32.lib,advapi32.lib,user32.lib等和其他非MSVC特定的文件)。我的问题是,不是.lib文件用于静态链接?如果是,那么为什么最终的exe只有大约500 KB? .lib都不是导入库。

    如果不是,那么link默认使用静态或动态链接? cl给出的/MD在这里有什么作用吗?

回答

2

原始的C运行时库从来没有想过必须支持从多个模块构建的程序。它包含全局变量,如errnostdout以及具有隐式全局状态的函数,如strtok()malloc()。您可以将DLL与他们自己的CRT副本链接起来,但这对设计DLL接口的方式提出了相当苛刻的要求。你必须非常小心地对从不依赖于CRT状态。获得这个错误几乎不可能诊断运行时错误行为。

对此的解决方法是在您的过程中只有一个一个 CRT副本。这是/ MD完成的,你最终会依赖于存储在DLL中的CRT版本。由所有模块共享。像msvcr120.dll一样,由VS2013使用。

编译器需要知道这个,以便它可以正确使用该DLL版本。一个简单的例子是errno,它是一个带有/ MT的全局变量,但是被宏编辑为带有/ MD的函数调用,因此只有DLL中的一个全局用于跟踪最后一个已知值。如果在编译器的.h文件中使用/ MD,则将定义_DLL宏。

另外一个副作用是编译器自动为msvcrt.lib或libcmt.lib插入链接指令(相当于#pragma注释)。旨在帮助您避免错误,并省略明确指定CRT库链接指令的需求。如果出现错误,则很难诊断链接器错误消息。与您尝试链接.obj或。时获得的种类不同。lib文件与/ MT和/ MD不匹配。哪一个当然不能正常工作,你不能对两者都有依赖性。

中的.libs都不是导入库

你的名字,ole32.lib,advapi32.lib,USER32.LIB列出的那些,其实都是导入库。它们是标准的操作系统DLL。在运行时,程序将加载相应的DLL,从调试器中可以很容易看到。对于VS,你会在输出窗口中看到它。值得注意的是,这些DLL实际上使用了与您的程序不同的CRT,它们绑定到c:\ windows \ system32 \ msvcrt.dll。 winapi经过精心设计,永远不会造成这个问题。

做链接使用静态或动态链接默认

没有默认值,它取决于你链接的.lib。区分静态链接库和导入库。导入库是在构建DLL时创建的。它是一个不包含代码的小文件,只是DLL中导出函数的名称,因此链接器知道将条目放入程序的导入表中。当程序启动时,DLL依赖项被解析并且导入的函数被加载器绑定。