我有一个C ++可执行文件,我正在动态链接几个库(Boost,Xerces-c和自定义库)。
我明白为什么如果我选择静态链接这些库(relevant SO question here),我会要求.lib / .a文件。但是,如果我动态地链接这些外部库,为什么在链接我的可执行文件时需要提供相应的.lib / .so库文件?
答案 0 :(得分:8)
编译器不知道动态链接,只知道通过其原型存在一个函数。链接器需要lib文件来解析符号。 DLL的lib包含其他信息,例如函数所处的DLL以及它们的导出方式(按名称,按序列等).DLL的lib文件包含的信息比包含完整目标代码的lib文件少得多 - libcmmt我系统上的.lib是19.2 MB,但msvcrt.lib是“仅”2.6 MB。
请注意,此编译/链接模型此时已接近40年,并且在大多数平台上超过动态链接。如果它是今天设计的,动态链接将是一流的公民(例如,在.NET中,每个程序集都有丰富的元数据,准确描述它导出的内容,因此您不需要单独的头文件和库。)
答案 1 :(得分:2)
Raymond Chen撰写了几篇关于Windows特定内容的博客文章。从The classical model for linking开始,然后使用Why do we have import libraries anyway?进行跟进。
总而言之,历史已将编译器定义为了解详细类型信息的组件,而链接器仅知道符号名称。因此链接器最终创建没有类型信息的.DLL,因此想要与之链接的程序需要某种元数据来告诉它如何导出函数以及它们采取和返回的参数类型。
.DLL没有直接链接所需的所有信息的原因是历史性的,而不是技术限制。
答案 2 :(得分:1)
首先,链接器插入链接时存在的库的版本,以便在更新库版本时您有可能使程序正常工作。系统上可以存在多个版本的共享库。
答案 3 :(得分:1)
链接器的作用是验证是否考虑了所有未定义的符号,包括静态内容或动态内容。
默认情况下,它会坚持所有符号都存在。
但是,这只是默认值。请参阅-z和--allow-shlib-undefined以及朋友。
答案 4 :(得分:0)
也许这个动态链接是通过导入库完成的(函数在定义之前有__declspec(dllimport))。
如果这是比compilator预期的那样,那么声明了__imp_symbol函数并且该函数负责将调用转发到动态加载的正确库。
在使用__declspec(dllimport)关键字
答案 5 :(得分:0)
这是一个非常简洁的描述,可能会有所帮助。静态链接将运行程序所需的所有代码放入可执行文件中,以便找到所有内容。动态链接意味着一些必需的代码不会被放入可执行文件中,并且会在运行时找到。我在哪里找到它?函数x()有吗?如何调用函数x()?这就是当你动态链接时库告诉链接器的内容。