2010-01-08 105 views
14

我有一个C++可执行文件,我正在动态链接几个库(Boost,Xerces-c和自定义库)。为什么C++链接器在构建期间需要库文件,即使我是动态链接?

我明白为什么我会要求.lib/.a文件,如果我选择静态链接这些库(relevant SO question here)。但是,为什么我需要在链接我的可执行文件时提供相应的.lib/.so库文件,如果我是动态链接到这些外部库?

+2

链接器需要知道哪个DLL包含需要解析的导出。 .lib文件提供了此信息。 – 2010-01-08 20:10:49

回答

8

编译器不知道动态链接,它只是知道函数通过它的原型存在。链接器需要lib文件来解析符号。 DLL的lib包含附加信息,比如函数所在的DLL以及它们如何导出(通过名称,序号等)。DLL的lib文件包含的信息比包含完整对象代码的lib文件要少得多 - libcmmt我的系统上的.lib是19.2 MB,但msvcrt.lib是“仅”2.6 MB。

请注意,此编译/链接模型在这一点上已有近40年的历史,并且早于大多数平台上的动态链接。如果它是今天设计的,动态链接将成为头等公民(例如,在.NET中,每个程序集都有丰富的元数据,准确描述了它的输出内容,因此您不需要单独的头文件和库。)

+3

所以,如果我正确理解这一点:作为'隐式'动态链接(构建期间与.lib链接,在运行时使用DLL)的替代方案 - 我可以'显式'链接在运行时通过使用(在Windows上)LoadLibrary()加载DLL和GetProcAddress()以返回指向我调用的方法的函数指针。这是更多的代码编写,但在编译时我不需要.lib。 – 2010-01-11 14:52:17

+0

你的理解是正确的。 – Michael 2010-01-11 17:21:07

1

有一件事,链接器插入链接时存在的库的版本,以便在程序库版本更新时有一定程度的工作机会。系统上可以存在多个版本的共享库。

1

链接器具有验证您的所有未定义符号是否包括静态内容或动态内容的工作。

默认情况下,它坚持所有符号都存在。

但是,这只是默认设置。请参阅-z和--allow-shlib-undefined以及朋友。

0

也许这个动态链接是通过导入库完成的(函数在定义之前有__declspec(dllimport))。
如果这是编译器希望声明__imp_symbol函数的方式,并且此函数负责将调用转发到动态加载的正确库。
这些功能是在符号与__declspec(dllimport)关键字链接过程中生成的。关键字

2

Raymond Chen写了一些关于这个特定于Windows的博客文章。从The classical model for linking开始,然后跟进Why do we have import libraries anyway?。总之,历史已经将编译器定义为知道详细类型信息的组件,而链接器只知道符号名称。因此,链接程序最终创建没有类型信息的.DLL,因此希望与它链接的程序需要某种类型的元数据来告诉它如何导出函数以及它们返回和返回哪些参数类型。

原因.DLL没有您需要直接与它们链接的所有信息是历史性的,而不是技术限制。

0

这是一个非常简单的说明,可能有所帮助。静态链接将运行程序所需的所有代码放入可执行文件中,以便找到所有内容。动态链接意味着一些所需的代码不会被放入可执行文件中,并会在运行时找到。我在哪里找到它?函数x()在那里?如何调用函数x()?这是图书馆在动态链接时告诉链接器的内容。

相关问题