Gcc 非常奇怪的链接器行为
这很奇怪,因为我能够通过删除对libm的引用来消除下面的错误Gcc 非常奇怪的链接器行为,gcc,linker,ld,Gcc,Linker,Ld,这很奇怪,因为我能够通过删除对libm的引用来消除下面的错误 gcc -o example example.o -Wl -L/home/kensey/cdev/lib -L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -L/usr/lib/x86_64-linux-gnu -lm -lrt -ldl -lcdev -L/home/kensey/www.tools/gplot-lib -lgplot -L/home/kensey/w
gcc -o example example.o -Wl -L/home/kensey/cdev/lib -L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -L/usr/lib/x86_64-linux-gnu -lm -lrt -ldl -lcdev -L/home/kensey/www.tools/gplot-lib -lgplot -L/home/kensey/www.tools/gd1_3ret -lgd -lxml2 -lcurl
/usr/bin/ld: /home/kensey/www.tools/gplot-lib/libgplot.a(set.o): undefined reference to symbol 'floor@@GLIBC_2.2.5'
/usr/bin/ld: note: 'floor@@GLIBC_2.2.5' is defined in DSO /usr/lib/x86_64-linux-gnu/libm.so so try adding it to the linker command line
/usr/lib/x86_64-linux-gnu/libm.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status
因此,如果我删除命令的
-lm
部分,就不会得到错误。然而,我想知道是否有人知道为什么删除对所需库的引用会解决这个问题。链接器如何知道要查找哪个库?还有-有没有一种方法可以查询一个构建的可执行文件并说“您解析了对“floor”的引用的哪个库?”?显然,有些事情我不明白,这让我很困扰 很难说。由于命令行中有自定义库目录,-lm
可以链接不兼容的替代版本。如果没有-lm
,链接器可能会引入它的另一个版本,因为您链接的某个库需要它
确保strace
两个调用,并查看libm.so
在这两种情况下来自何处
顺便说一句,
-Wl
开关似乎什么也不做,而且-L/usr/lib/x86_64-linux-gnu
被提到了两次。也许,您的库搜索路径(/usr/local/lib/或/usr/lib/,…)不包含64位libm,因此如果您使用L
标志指定,gcc无法找到它。如果只指定目录,它看起来可以找到正确的目录。因此,您可以尝试:
LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu
使用
-lm
一种解释可以是:
可能有一个在libm之外定义的弱链接函数foo
,被libm内部定义的强链接版本foo
所取代,而正是这个强链接版本调用了未定义的函数
这将解释添加库如何导致未定义的函数错误。对发生的情况的解释非常简单:
libgplot.a
依赖于libm.so
,但是链接行上-lm
和-lgplot
的顺序是错误的。
链接行上的库的顺序不会改变。一般来说,系统库(-lpthread
,-lm
,-lrt
,-ldl
)应遵循链接线上的所有其他内容-lm
时,libm.so.6
仍然被链接行后面出现的其他库拉入链接中(libgd
,libxml2
或libcurl
),因为该库依赖于libm.so.6
)。但是现在,libm.so.6
在链接行中的位置正确,所以一切正常这证实了上述解释。我已经解决了与导出LDFLAGS=“$LDFLAGS-lm”相同的问题,只需添加到答案列表中,这是一个信息性问题。这与上面提出的问题无关,但是,解释与错误消息有关:注意:“some_reference”是在DSO some中定义的。因此,请尝试将其添加到链接器命令行中我刚刚遇到了类似的问题;我记得在过去的gcc中,库的顺序并不重要(至少在我处理的案例中不重要)。有人注意到,行为似乎在4.4和4.5之间发生了变化 在我的例子中,我通过在以下位置进行链接来消除错误消息:
g++ -Wl,--copy-dt-needed-entries [options] [libraries] [object files] -o executable-file
使用以下命令:
administrator@administrator-Veriton-M200-H81:~/ishan$ gcc polyscanline1.cpp -lglut -lGLU -lGL -lm
请注意,符号已进行版本控制。它仍然适用吗?@MaximYegorushkin:不确定,抱歉。我认为未定义符号的版本与我可能的诊断是正交的。好吧,我又玩了一些,如果我把-lm放在link命令的末尾,将其列为最后一个库,我不会得到错误。非64位libm的理论可能仍然如此,因为它可能在命令末尾到达-lm之前“找到正确的一个”,因此-lm基本上被忽略。仅供参考-我通过“ar-t”查询了libm,它列出了库的内容。因此,这意味着它的64位/searchable.open(“/lib/x86_64-linux-gnu/libm.so.6”,O|RDONLY | O|u CLOEXEC)=3读(3,“\177ELF\2\1\1\0\0\0\0\0\0\0\0\0pU\0\0\0\0\0”…,832)=832 fstat 3,{st\u mode S=S\ifu reg}44,st\u size=1022320,{
kensey@kensey:~/cdev$strace./example 2>&1|grep libm open(/usr/lib/x86|u 64-linux-gnu/libmysqlclient.so.18),O|RDONLY | O|u CLOEXEC)=3 open(/lib/x86|u 64-linux-gnu/libm.so.6”,O|RDONLY | O|CLOEXEC)=3
因此,我不确定这是一个问题的原因,但幸运的是它消失了。我想教训是:确保图书馆排在其他可能引用它们的图书馆之后。strace可能有一种方法可以做更多的调查,但我不熟悉这个工具。谢谢你的帮助!事实上,在我看来,这是相对于早期版本的GNU工具链的一种行为改变。如果我没记错的话,过去给出的库的顺序对于gcc来说是不相关的,它足够聪明地找到了符号。在AIX上使用xlC时,如果我过去也没有记错的话,顺序很重要,
-Wl
选项后面通常跟一个逗号(将逗号后面的文本作为选项传递给链接器),您打算用它做什么?GCC版本与此无关,你说的是一个链接器的改变,而不是编译器的改变;明确添加-lm
是问题所在。非常感谢。你能解释一下这是怎么回事吗?-lm
用于链接标准C数学库我的问题并不完全是原始问题,但在我的LDFLAGS定义末尾的makefile中添加-lm是有效的。谢谢