背景
平台: Linux
一款c++应用程序(g++ 9.3.0)接入一个第三方SDK(g++ 4.9.3).so,并且该SDK内部静态依赖libstdc++(对应链接选项命令-static-libstdc++)
场景
在这款c++应用程序中使用标准库输出函数std::cout, 一编译运行后直接signal fault, gdb bt查看堆栈奔溃在这个函数std::cout 里边,并且这个奔溃显示调用到第三方库的so中的std::cout中,并不是依赖的应用程序本地的libstdc++库
分析
分析在编译本地c++应用程序时使用的编译命令如下
假设程序文件为test.cpp
假设第三方库为libthird.so
g++ -g -o test test.cpp -I./ -L./ -lthird -Wl,-rpath="/home/thirdPath"
这里由于test依赖第三方库third,而第三方库静态依赖了libstdc++,所以在third中引入了g++ 4.9.3 版本对应的std::cout实现,而test动态链接third,但是在test程序装载链接时,由于third先于test自身动态依赖的libstdc++库,所以将third中的std::cout符号先加载到了符号表,导致test执行程序时的std::cout执行到了third中,而由于编译test的g++版本为9.3.0(链接的对应的libstdc++库),而我们也知道一般我们是不建议混用不同编译器版本的c++库使用的,容易出现abi兼容问题,导致莫名的crash,而这里也证实了这个问题,对于不同的libstdc++ 库可能底层实现存在差异,编译器编译时可能存在差异,所以这里通过在编译test时优先链接test本身的libstdc++库来解决问题,通过以下编译命令
g++ -g -o test test.cpp -I./ -L./ -lstdc++ -lthird -Wl,-rpath="/home/thirdPath"