我们最近收到了一份报告,因为GCC 5.1,libstdc ++和Dual ABI.似乎Clang不知道GCC内联命名空间更改,因此它基于一组命名空间或符号生成代码,而GCC使用另一组命名空间或符号.在链接时,由于缺少符号而存在问题.
如果我正确地解析双ABI页面,它看起来像是一个转动的问题,_GLIBCXX_USE_CXX11_ABI并abi::cxx11带来一些额外的困难.Red Hat的博客可以在GCC5和C++ 11 ABI以及GCC-5.1案例和两个C++ ABI上阅读更多内容.
下面是一台Ubuntu 15机器.该机器提供GCC 5.2.1.
$ cat test.cxx
#include <string>
std::string foo __attribute__ ((visibility ("default")));
std::string bar __attribute__ ((visibility ("default")));
$ g++ -g3 -O2 -shared test.cxx -o test.so
$ nm test.so | grep _Z3
...
0000201c B _Z3barB5cxx11
00002034 B _Z3fooB5cxx11
$ echo _Z3fooB5cxx11 _Z3barB5cxx11 | c++filt
foo[abi:cxx11] bar[abi:cxx11]
Run Code Online (Sandbox Code Playgroud)
如何使用两个装饰生成带符号的二进制文件(红帽博客称之为"共存")?
或者,我们可以选择哪些选项?
我正试图为用户实现"它只是工作".我不在乎是否存在两个具有两种不同行为的弱符号(std::string缺少写时std::string[abi:cxx11]复制,同时提供写时复制).或者,一个可以是另一个的别名.
Debian在Debian Bug报告日志中 …
Java Native Interface(JNI)是否受C++ ABI兼容性问题的影响?
我正在开发一个Java应用程序.我想使用Java Native Interface(JNI)来调用C++库中的函数.我可以访问C++库的代码,但我可以重建它,但我可能需要.(例如,我可以静态链接C++运行时.)
我可以要求我的用户拥有JRE 6或更高版本,但我不能要求他们拥有任何特定的C++运行时.
一位同事向我指出了这篇博客文章:http://www.trilithium.com/johan/2005/06/static-libstdc/,它建议不要使用动态加载的C++代码.
另一位同事向我指出了这个错误报告:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4694590,详细说明了如何在Java 1.4.2中解决这些问题.
根据我的理解,问题的要点是libstdc ++的二进制接口经常发生变化.如果C++应用程序加载了使用不同编译器构建的C++共享库,则会同时将两个不兼容的libstdc ++库加载到内存中.
错误报告解释了Java 1.4.2的解决方案:"我们静态链接JDK中的C++运行时并启用链接器脚本以隐藏libstdc ++和其他内部符号中的符号.结果,这些符号对JNI代码变得不可见,并且当某些符号时本机代码需要调用C++运行时,调用将使用适当的libstdc ++解析.所以.还有两个libstdc ++.所以同时加载,但它应该是良性的."
我有几个问题.
首先,OpenJDK是否继续采用这种方法?
[ 编辑:我在OpenJDK的build-dev邮件列表中问过这个问题.答案是肯定的,HotSpot仍然静态地链接libstdc ++,但显然"大多数Linux发行版补丁出来".另一位开发人员指出,这甚至不需要补丁:"设置STATIC_CXX = false应该足够了(默认为true)."]
其次,即使在这种情况下,拥有两个不兼容的libstdc ++是否真的是良性的.所以同时加载?
第三,这种方法(隐藏JDK中的符号)是否解决了所有兼容性问题?
上面引用的博客文章警告说"针对不同ABI编译的代码根本不是二进制兼容的".后来,"语言运行时支持通常依赖于一些共享数据,例如访问某种锁或全局数据结构(类似于C程序需要共享错误的方式)."
这使得听起来无法解决问题.
再说一次,也许ABI不兼容不再是问题.博客文章已有六年多了.另一个stackoverflow问题(GCC ABI兼容性)的答案断言"自从gcc-3.4.0起,ABI是向前兼容的".这是成功的吗?
我对这些问题的任何指导表示感谢.(嘿,谢谢阅读所有这些!)
EDITS
我的问题变得越来越长,所以我没有详细说明.解决威尔的评论:
有时我从不同的设计团队获得图书馆.一个使用gcc 3.x,另一个使用gcc 4.x. 如何识别这两个库是否兼容?我知道它与libstdc ++有关,但你能否给我一个明确的答案?
我正在尝试重新编译现有的 C++ 应用程序。不幸的是,我必须依赖一个专有库,我只有一个预编译的静态存档。
我使用 g++ 版本 7.3.0 和 ld 版本 2.30。
无论它是用什么 GCC 版本编译的,它都是古老的。
头文件定义了方法:
class foo {
int bar(int & i);
}
Run Code Online (Sandbox Code Playgroud)
如图nm lib.a所示,库存档包含相应的导出函数:
T bar__4fooRi
Run Code Online (Sandbox Code Playgroud)
nm app.o显示了我最近使用不同类型的名称修饰的编译器:
U _ZN4foo9barERi
Run Code Online (Sandbox Code Playgroud)
因此,链接器无法解析库提供的符号。
是否有任何选项可以选择名称修饰算法?
我可以引入地图或明确定义损坏的名称吗?
我正在Unix机器上编译OpenSSL.默认编译器是GCC-4.4.7.我把另一个编译器GCC-5.2.0放在另一个文件夹中.我通常会在备用编译器的前面添加路径,$PATH以便gcc始终使用备用路径中的路径.
但现在我不确定我编译的库,有没有办法告诉哪个gcc用于编译我的库?还.o可以了解文件的解决方法.