为什么C++;链接器在生成过程中需要库文件,即使我正在动态链接? 我有一个C++可执行文件,我与几个库(Boost,XeSer-C和自定义LIBs)动态链接。

为什么C++;链接器在生成过程中需要库文件,即使我正在动态链接? 我有一个C++可执行文件,我与几个库(Boost,XeSer-C和自定义LIBs)动态链接。,c++,gcc,linker,visual-c++,C++,Gcc,Linker,Visual C++,如果我选择静态链接这些库(),我理解为什么我需要.lib/.a文件。但是,如果我正在对这些外部库进行动态链接,为什么在链接可执行文件时需要提供相应的.lib/.so库文件?编译器不知道动态链接,它只知道函数通过其原型存在。链接器需要lib文件来解析符号。DLL的库包含附加信息,如函数所在的DLL以及它们如何导出(按名称、顺序等)。DLL的库文件包含的信息比包含完整对象代码的库文件少得多。在我的系统上,libcmmt.lib为19.2 MB,但msvcrt.lib“仅”为2.6 MB 请注意,这个

如果我选择静态链接这些库(),我理解为什么我需要.lib/.a文件。但是,如果我正在对这些外部库进行动态链接,为什么在链接可执行文件时需要提供相应的.lib/.so库文件?

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


请注意,这个编译/链接模型现在已经有将近40年的历史了,并且早于大多数平台上的动态链接。如果它是在今天设计的,那么动态链接将是一个一流的公民(例如,在.NET中,每个程序集都有丰富的元数据,精确地描述它导出的内容,因此您不需要单独的头和库),链接器插入链接时存在的库的版本,以便在库版本更新时程序有一定的工作机会。一个系统上可以存在多个版本的共享库。

链接器的任务是验证所有未定义的符号是否都已包含在静态内容或动态内容中

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


然而,这只是默认值。请参阅-z、和--allow shlib undefined和friends。

也许此动态链接是通过导入库完成的(函数在定义之前有declspec(dllimport)。
如果这是编译器期望的方式,则声明了_imp_symbol函数,该函数负责将调用转发到动态加载的正确库。

这些函数是在符号与u declspec(dllimport)关键字链接的过程中生成的

Raymond Chen写了一些专门针对Windows的博客文章。从开始,然后跟进

总而言之,历史将编译器定义为了解详细类型信息的组件,而链接器只知道符号名称。因此,链接器最终创建了没有类型信息的.DLL,因此想要与之链接的程序需要某种元数据来告诉它函数是如何导出的,以及它们采用和返回的参数类型


DLL没有直接链接所需的所有信息的原因是历史原因,而不是技术限制。

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

链接器需要知道哪个DLL包含需要解析的导出。.lib文件提供此信息。您是询问.dll还是.so?linux的答案将是不同的。因此,如果我正确理解这一点:作为“隐式”动态链接的替代方法(在构建期间针对.lib链接,在运行时使用DLL)-我可以在运行时使用(在Windows上)LoadLibrary()加载DLL和GetProcAddress()进行“显式”链接返回指向我正在调用的方法的函数指针。要编写的代码更多,但在构建时我不需要.lib。