G++编译二进制时GLIBCXX版本的决定主体及依赖异常排查
我刚好碰过类似的问题,结合你的场景(CentOS6.8 + G++4.9.3 + Boost1.41.0的file_lock),给你拆解清楚这三个问题:
1. GLIBCXX版本由谁决定?
GLIBCXX_xxx是GCC自带的标准库libstdc++.so的版本符号,它的核心决定因素是你使用的GCC/G++版本——不同版本的GCC会对应不同版本的libstdc++,也就会支持不同范围的GLIBCXX版本(比如G++4.9.3对应的libstdc++最高支持到GLIBCXX_3.4.19)。
但这里有个关键:最终你的二进制/共享库实际依赖哪个GLIBCXX版本,不是由编译器版本直接硬定的,而是由编译时实际用到的标准库函数/符号决定的。比如你用G4.9.3,但如果代码里只用到C98的基础函数,那可能只会依赖GLIBCXX_3.4.13甚至更低的版本;但如果用到了高版本才有的函数,就会触发更高版本的依赖。
2. 是否与源码相关?
完全相关,这也是你遇到的问题的核心原因。
你的其他项目用同款编译器编译没有这个依赖,说明那些项目的代码(包括依赖的库)没有调用到需要GLIBCXX_3.4.15的标准库函数;但这个用到boost::interprocess::file_lock的库不一样——要么是你的代码里直接用了某个C++11及以后的特性,要么是Boost 1.41.0的file_lock内部实现,调用了libstdc++中GLIBCXX_3.4.15才引入的符号(比如某些线程相关的函数、内存管理函数,或者STL容器的扩展方法)。
你可以用objdump -x libmylib.so | grep GLIBCXX命令,直接看到这个库依赖的所有GLIBCXX版本符号,再结合nm -D /usr/lib64/libstdc++.so.6 | grep GLIBCXX_3.4.15对比,就能找到具体是哪个函数触发的依赖。
3. 编译器是否会因代码特性指定依赖版本?
是的,G++在编译过程中,会根据你代码中使用的具体标准库特性,自动选择对应的libstdc++符号版本。
举个例子:如果你的代码里用了std::thread(C11新增),而G4.9.3的libstdc++中,std::thread的实现依赖GLIBCXX_3.4.15的符号,那么编译器就会在生成的目标文件中标记需要这个版本的依赖。当链接成共享库后,运行时动态链接器就会检查系统的libstdc++.so.6是否支持这个版本——这就是你报错的原因。
简单来说,编译器不会凭空给你加高版本依赖,只有当代码(或依赖的库)用到了对应版本才有的功能时,才会生成对应的依赖要求。
补充一个快速排查方向
你可以检查Boost的编译参数:如果Boost是用系统自带的旧GCC编译的,可能会和你现在用的G++4.9.3产生版本冲突;或者尝试编译时加上-static-libstdc++参数,把libstdc++静态链接到你的共享库中,这样就能绕过系统的旧版本限制。
内容的提问来源于stack exchange,提问作者Jinoh Kim




