指定O2标志时,gcc链接到错误的GLIBCXX版本

时间:2015-05-28 18:29:14

标签: c++ linux gcc linker ld

我有一个使用Makefile构建的共享库文件。我遇到了一个问题,在构建库之后,我遇到了可怕的GLIBCXX_ not found链接器错误。

这种情况特别奇怪。当我使用-g3标记编译时,我没有收到错误。如果我使用-O2进行编译,则会收到错误。

因此,当我使用-O2进行编译,并针对已编译的ldd文件运行.so时,我得到:

$ ldd MYLIB.so.1
./MYLIB.so.1: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.9' not found (required by ./MYLIB.so.1)
        linux-vdso.so.1 =>  (0x00007fff21e8d000)
        libz.so.1 => /lib64/libz.so.1 (0x00002b2cd4c40000)
        libpng12.so.0 => /usr/lib64/libpng12.so.0 (0x00002b2cd4e54000)
        libjpeg.so.62 => /usr/lib64/libjpeg.so.62 (0x00002b2cd5079000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00002b2cd529b000)
        libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00002b2cd54b7000)
        libm.so.6 => /lib64/libm.so.6 (0x00002b2cd57b8000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00002b2cd5a3b000)
        libc.so.6 => /lib64/libc.so.6 (0x00002b2cd5c49000)
        /lib64/ld-linux-x86-64.so.2 (0x0000003891400000)

所以在这里,由于某种原因,/usr/lib64/libstdc++.so.6正在寻找GLIBCXX_3.4.9/usr/lib64/libstdc++.so.6中不存在,正如我们使用strings实用程序所看到的那样:

$ strings /usr/lib64/libstdc++.so.6 | grep GLIBCXX
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_FORCE_NEW

因此,为了进一步调查此问题,我针对已编译的nm文件运行.so,并尝试查找要查找的符号GLIBCXX_3.4.9

$ nm --demangle MYLIB.so.1 | grep GLIBCXX_3.4.9
  U std::ostream& std::ostream::_M_insert<unsigned long>(unsigned long)@@GLIBCXX_3.4.9
  U std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)@@GLIBCXX_3.4.9

好的,所以看起来一些标准的C ++ ostream代码需要GLIBCXX_3.4.9。好的......但它只是这一个似乎需要GLIBCXX_3.4.9的符号。其他所有内容都与GLIBCXX_3.4正确链接:

    $nm --demangle MYLIB.so.1 | grep GLIBCXX
      U std::string::find(char const*, unsigned long, unsigned long) const@@GLIBCXX_3.4
      U std::string::compare(char const*) const@@GLIBCXX_3.4
      U std::string::compare(std::string const&) const@@GLIBCXX_3.4
      U std::logic_error::what() const@@GLIBCXX_3.4
      U std::runtime_error::what() const@@GLIBCXX_3.4
      U std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::str() const@@GLIBCXX_3.4
      U std::basic_iostream<char, std::char_traits<char> >::~basic_iostream()@@GLIBCXX_3.4

... etc ...

那么可能是什么原因造成的?为什么一个特定的符号链接GLIBCXX_3.4.9,但其余的不符合?更奇怪的是 - 只有在我使用-O2进行编译时才会发生这种情况。

我对此感到非常困惑。那么,为什么会出现这种情况的原因有哪些?链接器/编译器链如何确定在哪个GLIBCXX版本中找到特定符号?

1 个答案:

答案 0 :(得分:2)

这只是意味着您使用比/usr/lib64/libstdc++.so库所属的更新的GCC进行编译,并且您没有告诉动态链接器如何找到正确的libstdc ++。所以

对GLIBCXX_3.4.9的引用意味着您至少使用GCC 4.2.0编译,但系统libstdc ++。所以来自旧版本4.1.1或4.1.2。

事实上它只是-O2的一个问题并不真正相关,如果你用一个较新的GCC编译你需要使用它的libstdc ++。所以,句号。似乎除非你使用-O2进行编译,否则你实际上并没有对较新的libstdc ++产生硬依赖。所以这只是偶然的,如果对代码进行任何小的更改导致它的优化程度略有不同,它可能会改变。

您需要阅读https://gcc.gnu.org/onlinedocs/libstdc++/faq.html#faq.how_to_set_pathshttps://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dynamic_or_shared.html#manual.intro.using.linkage.dynamic

  

为什么一个特定的符号链接GLIBCXX_3.4.9,但其余的没有?

因为GCC 3.4和4.2之间的其他符号和旧libstdc ++中符号的版本没有变化。所以与构建可执行文件时链接的符号相同。

未找到的符号是GCC 4.2中新增的符号,因此它被赋予了较新的符号版本,并且在较旧的库中找不到它。