很奇怪的链接器行为

时间:2012-03-29 22:33:49

标签: 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/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'的引用?显然,有些事情我不明白,这让我感到烦恼......

8 个答案:

答案 0 :(得分:83)

对正在发生的事情的解释非常简单:

  1. 您的libgplot.a取决于libm.so,但链接行上-lm-lgplot的顺序错误。 链接行上的库的顺序为 matter。通常,系统库(-lpthread-lm-lrt-ldl)应该跟随链接行上的所有其他内容。

  2. 当您从链接行中删除-lm时,libm.so.6仍会被稍后在链接行显示的其他库(libgd,{{ 1}}或libxml2)因为该库取决于libcurl。但现在libm.so.6位于链接行的正确位置,所以一切正常。

  3.   

    如果我将-lm放在link命令的末尾,将其列为最后一个库,我就不会收到错误。

    这证实了上述解释。

答案 1 :(得分:8)

我用export LDFLAGS="$LDFLAGS -lm"

解决了同样的问题

答案 2 :(得分:6)

或许,您的库搜索路径(/ usr / local / lib /或/ usr / lib /,...)不包含64位libm,因此如果您使用l标志指定gcc,则无法找到它。如果您只指定它看起来可以找到正确的目录。所以你可以尝试:

LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu

并使用-lm

答案 3 :(得分:3)

很难说。因为命令行中有自定义库目录,所以可以想象-lm链接不兼容的替代版本。如果没有-lm,链接器可能会引入另一个版本,因为您链接的库之一需要它。

确保strace两次调用并查看两种情况下libm.so的来源。

BTW,-Wl切换似乎什么都不做,-L/usr/lib/x86_64-linux-gnu被提及两次。

答案 4 :(得分:2)

只是要添加到答案列表中,http://fedoraproject.org/wiki/UnderstandingDSOLinkChange这是有用的信息。它与上面提到的问题无关,但是,解释与错误消息/usr/bin/ld: note: 'some_reference' is defined in DSO some.so so try adding it to the linker command line

有关

答案 5 :(得分:1)

一个解释可以

可能存在一个在libm之外定义的弱链接函数foo,它被libm中定义的foo的强链接版本所取代,而这是一个调用未定义函数的强连接版本

这可以解释添加库如何导致未定义的函数错误。

答案 6 :(得分:1)

我遇到了类似的问题;我记得在过去的gcc中,库的顺序并不重要(至少在我使用过的情况下并不重要)。在this question here中,有人注意到这种行为似乎在4.4和4.5之间发生了变化。

就我而言,我通过在以下位置进行链接来消除错误消息:

 g++ -Wl,--copy-dt-needed-entries [options] [libraries] [object files] -o executable-file

答案 7 :(得分:-1)

使用此:

administrator@administrator-Veriton-M200-H81:~/ishan$ gcc polyscanline1.cpp -lglut -lGLU -lGL -lm