我有一个静态库staticLibA.lib
,它提供了许多功能。其中一些需要该库中未提供的某些外部函数。
此外,我定义了一个动态库dynLib.dll
,该库使用了某些静态库函数,但没有一个函数需要上述外部函数。
但是,如果我链接动态库,尽管没有必要使用外部符号,但仍会得到未解析的外部符号。
编译器是否应仅从目标程序所需的静态库中选择函数?
这里有个例子
staticLib.lib:
// staticLib_fileA.c
extern void extLibFunction();
void slib_funcA(){
extLibFunction();
// some stuff
}
// staticLib_fileB.c
void slib_funcB(){
// some stuff
}
dynLib.dll
// dynLib.c
void dyn_func(){
slib_funcB();
// some stuff
}
dynLib.dll
的编译/链接带有未解决的符号extLibFunction
:
staticLib.lib(staticLib_fileA.obj) : error LNK2001: unresolved external symbol extLibFunction
有没有解决的办法?一些编译器设置要求仅链接实际所需的符号。 解决方法是一些虚拟的实现,但是我更喜欢某种方法,该方法仅在需要lib的用户时才强制他们做些事情
答案 0 :(得分:0)
与静态库不同,DLL不能包含未解析的符号(引用)。 DLL允许二进制文件在运行时访问所有符号,甚至不需要其中的一些。 库由.o文件制成。库中的某些.o文件可能包含程序中未使用的符号。 在链接时,只要您不需要这些未解析的符号或.o文件中包含未解析的符号的任何其他符号,您的静态库就可以具有未解析的符号。使用DLL,事情就不一样了,即使您的程序不需要它们,也必须在链接时解析所有引用。
答案 1 :(得分:0)
似乎由于fileB.obj
中的其他功能导致fileA.obj
的依赖性,目标文件整体上彼此具有依赖性。
因此,即使使用该依赖关系的函数永远不会在链接的二进制文件中被调用(或在dll:情况下被导出),甚至也不会在{{ 1}}。
如果启用了“功能级别链接”和“ Comdat折叠”,这似乎是正确的。
雷蒙德·陈(Raymond Chen)在围绕链接原理的一系列博客文章中解释了为什么这样做是正确的。
https://devblogs.microsoft.com/oldnewthing/tag/linker
事实证明,即使采用了先进的技术(如上面提到的),第一步也是经典的方法,必须解决所有符号,即使随后的优化将再次去除这些符号。