【发布时间】:2015-05-28 18:29:14
【问题描述】:
我有一个使用 Makefile 构建的共享库文件。我遇到了一个问题,在构建库之后,我会遇到可怕的GLIBCXX_ not found 链接器错误。
这个案子特别奇怪。当我使用 -g3 标志编译时,我没有收到错误消息。如果我用-O2 编译,我会得到错误。
所以,当我使用-O2 编译并针对已编译的.so 文件运行ldd 时,我得到:
$ 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
所以,为了进一步调查,我对编译后的 .so 文件运行 nm,并尝试找到正在寻找 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 版本?
【问题讨论】:
-
最可能的解释是您安装的头文件与您安装的库不一致,这种方式仅在您使用优化进行编译时才会出现问题。解决此问题的最简单方法是完全卸载编译器和 C++ 运行时库,然后重新安装它们。 (您应该在单用户模式下执行此操作,因为您将不得不暂时中断依赖于 C++ 运行时库的所有内容。)确保您只安装一个内部一致的编译器,来自您的发行版,而不是第三方.
-
(add'l:) 有几种不同程度的笨拙的第三方尝试强制当前编译器生成只需要旧版本符号的可执行文件。 这些都不是安全或可靠的。 如果您尝试做类似的事情,请停止。如果您出于某种原因需要仅依赖于旧符号版本的二进制文件,则必须使用旧编译器对其进行编译。如果您出于其他原因需要更新的编译器,那么您就是 SOL。
-
@zwol,感谢您的回复。我在这里没有做任何奇怪的事情,比如试图强制编译器使用旧的符号版本。我正在使用旧版本的 gcc 进行编译。