std::regex and dual ABI
std::regex and dual ABI
今天我发现了一个有趣的案例,即双libstdc++ABI影响库的兼容性。
长话短说,我有两个库,它们都在内部使用std::regex。一个是用CXX11 ABI构建的,另一个不是。当这两个库在一个可执行文件中链接在一起时,它在启动时崩溃(在输入main
之前(。
这些库是不相关的,并且不公开提及任何std::
类型的接口。我认为这样的库应该不受双重ABI问题的影响。显然不是!
问题可以通过这种方式轻松复制:
// file.cc
#include <regex>
static std::regex foo("(a|b)");
// main.cc
int main() {}
// build.sh
g++ -o new.o file.cc
g++ -o old.o file.cc -D_GLIBCXX_USE_CXX11_ABI=0
g++ -o main main.cc new.o old.o
./main
输出为:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted (core dumped)
无论我做什么,这个问题都会持续存在。file.cc
可以被制作成两个单独的源文件,编译成单独的共享库,这两个std::regex
对象可能有不同的名称,它们可以是全局的、静态的或自动的(然后需要从main
调用相应的函数(。这些都无济于事。
显然(这是我简短调查的结果(,libstdc++regex编译器有某种存储std::string
的内部静态数据,当两段与ABI不兼容的代码试图使用这些数据时,它会对std::string
对象的布局产生冲突。
所以我的问题是:
- 有解决这个问题的方法吗
- 这应该被认为是libstdc++中的一个错误吗
这个问题在g++/libstdc++的几个版本中都是可重复的(我在5.4到7.1中尝试了一些(。libc++不会出现这种问题。
问题源于libstdc++具有双重ABI的原因。从这两个重要的陈述中:(1(它被特别引入,以符合关于string
(以及与本讨论无关的其他(如何工作的新的第11标准;(2(_GLIBCXX_USE_CXX11_ABI
独立于方言工作,用于编译C++03和C++11。
regex
模块在第11个标准中引入,并在内部使用字符串。因此,您可以使用_GLIBCXX_USE_CXX11_ABI=0
构建c++-11(或更高版本(模板basic_regex
代码。这意味着您使用的是带有字符串的c++-11之前实现的c++-11regex
对象。
这样行吗?根据regex
使用字符串的方式,如果它确实依赖于新的实现(例如写入时禁止复制(,则为否,否则为是。会发生什么?任何东西
归根结底,您不应该在任何使用后c++-03方言(即c++-11、14、17…(的新代码上使用_GLIBCXX_USE_CXX11_ABI=0
,因为它引入了与标准对象上的新保证不兼容的实现,尤其是std::string
。
我可以使用标准>=c++-11的_GLIBCXX_USE_CXX11_ABI=0
吗?GCC开发人员注意到,您可以使用旧的ABI运行新的东西,这得益于使用旧的共享库运行新功能的可能性。然而,这可能不是一个好主意,也因为代码是在一个新的标准中,然而标准库不符合这个标准,以后可能会出现糟糕的结果。你的问题就是一个例子。你可以通过混合两个ABI,而我们在这里,这是行不通的。
如果您调用(例如(某个.so库中定义的foo(std::string const&)
(使用旧ABI编译(,_GLIBCXX_USE_CXX11_ABI=0
就非常有用。然后,在新的源文件中,您希望使用旧的ABI编译此源文件。但所有其他来源,你会保留一个新的ABI。
这个问题在g++/libstdc++的几个版本中都是可重复的(我在5.4到7.1中尝试了一些(。libc++不会出现这种问题。
libc++
不具有这种对偶性,即单个string
实现。
我没有给出一个明确的答案,这个例外是从哪里来的,或者为什么。我只能猜测,有一些与regex
、string
或locale
相关的共享全局资源在ABI之间没有明确区分。不同的ABI处理它的方式不同,可能导致任何事情,例如异常、段故障、任何意外行为。IMHO,我更喜欢遵守我上面提到的规则,这些规则最能反映_GLIBCXX_USE_CXX11_ABI
和双重ABI的意图。
- 海湾合作委员会手册中提到的"C++ ABI Specification"是什么?
- 链接器错误:未定义对"Reference_Genome::seq[abi:cxx11]"的引用
- 尝试从头开始实现Leetcode的FizzBuzz多线程问题。收到"libc++abi.dylib: terminating"错误
- 在AAPCS(ARM ABI)下,C/C++结构填充的稳定性如何
- 对于哪些 ABI,我可以使用 NDK v10e 构建 apk?
- C++ ABI 兼容性问题/张量流
- 了解 ELF 可执行SHT_NOTE部分".note.ABI-tag"
- 为什么库API+编译器ABI足以确保具有不同版本gcc的对象之间的兼容性
- E/libc++abi:终止于类型为google::protobuf::FatalException的未捕获异常
- libc++abi未定义符号:_ZTVN10__cxxabif120__si-class_type_infoE
- 如何在红帽上强制使用 cxx11 ABI?
- std::regex and dual ABI
- MRB_THROW会导致libc++abi.dylib中的错误
- abi-compliance-checker 中的扩展选项用于什么?
- C++ Linux 上的插件 ABI 问题
- 如果我只使用指向基类的指针,更改私有派生类是否会影响 ABI?
- Centos6 gcc6:编译简单的 c++11 测试文件时,默认的 ABI 不拾取
- 使用共享库版本支持不同 ABI 的最佳实践是什么?
- std::function, Clang 6.0 & MSVC (10.0017134.12) - 可能的 ABI 错误或必需的编译器标志
- 安腾C++ABI VTT含量