为什么GNULD在链接可执行文件和共享对象时解析符号不同? < >我有一个C++代码的小块,看起来像这样: #include <boost/timer/timer.hpp> int main(void) { boost::timer::auto_cpu_timer t; return 0; }

为什么GNULD在链接可执行文件和共享对象时解析符号不同? < >我有一个C++代码的小块,看起来像这样: #include <boost/timer/timer.hpp> int main(void) { boost::timer::auto_cpu_timer t; return 0; },c++,gcc,linker,ld,binutils,C++,Gcc,Linker,Ld,Binutils,一种解决方案是在命令行中明确地提到-lboost\u system,这是可行的。但是,我也可以做到: $ g++ -Wl,--copy-dt-needed-entries -o test test.cc -lboost_timer 根据ld文档“with--copy dt needed entries命令行中提到的动态库将在dt_needed标记之后递归搜索到其他库,以便解析输出二进制文件所需的符号”,所以这一切都是有意义的:ld从boost_定时器中发现,它还需要连接boost_系统,以解析

一种解决方案是在命令行中明确地提到
-lboost\u system
,这是可行的。但是,我也可以做到:

$ g++ -Wl,--copy-dt-needed-entries -o test test.cc -lboost_timer
根据ld文档“with--copy dt needed entries命令行中提到的动态库将在dt_needed标记之后递归搜索到其他库,以便解析输出二进制文件所需的符号”,所以这一切都是有意义的:ld从boost_定时器中发现,它还需要连接boost_系统,以解析所有符号

然而,我意识到这同样有效:

$ g++ -fPIC -shared -o test test.cc -lboost_timer
显然,我现在已经生成了一个共享对象,而不是一个可执行文件。显然,尽管如此,ld还是能够找出它需要将共享对象与boost_系统链接起来:

$ ldd test | grep boost_system
        libboost_system.so.1.54.0 => /usr/lib/libboost_system.so.1.54.0 (0x00007f385246e000)

所以我的问题是:为什么在构建共享对象和可执行文件时,符号分辨率不同?ld如何在不指定
--复制dt所需条目的情况下,找出我的共享对象应该与boost_系统链接

collect2命令中存在可能相关的差异。不同的命令将在下一步进行比较。右侧创建共享库(-fPic-shared),左侧是正常编译。

我的问题的直接答案是在
-[no-]allow shlib undefined
选项中,我想。从手册页:

默认行为是报告任何未定义符号的错误 如果链接器用于创建,则在共享库中引用 可执行文件,但如果链接器用于创建 共享图书馆

因此,当我使用
-shared
构建时,boost_系统中的符号是未定义的,但是ld的默认行为是不关心。可以告诉它要小心:

$ g++ -fPIC -shared -Wl,--no-allow-shlib-undefined -o test test.cc -lboost_timer
/usr/bin/ld: /tmp/cc6j1de3.o: undefined reference to symbol '_ZN5boost6system15system_categoryEv'
/usr/lib/libboost_system.so.1.54.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
类似地,我们可以告诉它在构建可执行文件时不要在意:

$ g++ -Wl,--allow-shlib-undefined -o test test.cc -lboost_timer
/tmp/ccUHoCIU.o: In function `__static_initialization_and_destruction_0(int, int)':
test.cc:(.text+0x7a): undefined reference to `boost::system::generic_category()'
test.cc:(.text+0x86): undefined reference to `boost::system::generic_category()'
test.cc:(.text+0x92): undefined reference to `boost::system::system_category()'
collect2: error: ld returned 1 exit status
但是,如果无法定义这些符号,创建二进制文件将失败


谢谢@CharlesBailey为我指明了正确的方向

您是否尝试过使用
-shared-z defs
?@CharlesBailey将
-z defs
添加到共享构建中确实会导致其中断(
test.cc:(.text+0x85):未定义对“boost::system::generic_category()”的引用。
)。查看
-z defs
时,我还指出了
-[no-]allow shlib undefined
,这实际上可以解释发生了什么。。。谢谢你的指点!这可能是个离题的问题。但是你的diff图像看起来很有趣。你能告诉我们你从哪里弄来的diff工具吗??
$ g++ -Wl,--allow-shlib-undefined -o test test.cc -lboost_timer
/tmp/ccUHoCIU.o: In function `__static_initialization_and_destruction_0(int, int)':
test.cc:(.text+0x7a): undefined reference to `boost::system::generic_category()'
test.cc:(.text+0x86): undefined reference to `boost::system::generic_category()'
test.cc:(.text+0x92): undefined reference to `boost::system::system_category()'
collect2: error: ld returned 1 exit status