std :: regex和双重ABI [英] std::regex and dual ABI

查看:71
本文介绍了std :: regex和双重ABI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天我发现了一个有趣的案例,即双重libstdc ++ ABI影响库的兼容性。

Today I have found an interesting case of the dual libstdc++ ABI affecting compatibility of libraries.

总之,我有两个库都使用std :: regex内部。一种是使用CXX11 ABI构建的,另一种则不是。当将这两个库链接到一个可执行文件中时,它会在启动时崩溃(在输入 main 之前)。

Long story short, I have two libraries that both use std::regex internally. One is built with the CXX11 ABI and one is not. When these two libraries are linked together in one executable, it crashes on startup (before main is entered).

这些库是不相关的,并且不会公开提及任何 std :: 类型的接口。我认为这样的库应该不受双重ABI问题的影响。显然不是!

The libraries are unrelated and do not expose interfaces that mention any std:: types. I thought such libraries should be immune to dual ABI issues. Apparently not!

可以很容易地以这种方式重现该问题:

The issue can be reproduced easily this way:

// 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 调用相应的函数)。

The issue persists whatever I do. file.cc can be made into two separate source files, compiled into separate shared libraries, the two std::regex objects may have different names, they can be made global, static or automatic (one will need to call corresponding functions from main then). None of this helps.

显然(这是我的简短调查得出的结果),libstdc ++ regex编译器具有某种内部静态数据,可存储 std :: string ,并且当两个不兼容ABI的代码段尝试使用该数据时,它会产生关于 std :: string 对象。

Apparently (this is what comes out of my short investigation) the libstdc++ regex compiler has some kind of internal static data that stores std::string, and when two ABI-incompatible pieces of code try to use that data, it gets conflicting ideas about the layout of std::string objects.

所以我的问题是:


  • 是否有解决此问题的方法?

  • 应将其视为libstdc ++中的错误吗?

问题在g ++ / libstdc ++的多个版本中都是可复制的(我尝试了5.4到7.1的几个版本)。使用libc ++不会发生。

The problem is reproducible in several versions of g++/libstdc++ (I tried a few from 5.4 to 7.1). It doesn't occur with libc++.

推荐答案

问题源于libstdc ++为什么具有双重ABI 。从这两个重要的陈述中可以看出:(1)在 string (以及与该讨论不相关的其他字符串)的工作方式方面,为了符合新的第11条标准而专门引入了该标准。 ; (2) _GLIBCXX_USE_CXX11_ABI 独立于方言工作,并用于将C ++ 03和C ++ 11一起编译。

The problem stems to the origin of why libstdc++ has dual ABI. From this two important statements: (1) it was specifically introduced to conform with the new 11th standard in regards to how string (and other that is not relevant for this discussion) works; (2) _GLIBCXX_USE_CXX11_ABI works independently of a dialect, and used to compile C++03 and C++11 together.

regex 模块在第11个标准中引入,并在内部使用字符串。因此,您可以使用 _GLIBCXX_USE_CXX11_ABI = 0 构建c ++-11(或更高版本)模板 basic_regex 代码。这意味着您正在使用c ++-11 regex 对象以及c ++-11之前的字符串实现。

regex module was introduced in the 11th standard, and uses strings internally. So you build your c++-11 (or higher) template basic_regex code with _GLIBCXX_USE_CXX11_ABI=0. That means you are using c++-11 regex object with a pre-c++-11 implementation of strings.

应该那工作吗?根据 regex 使用字符串的方式,如果它确实依赖于新的实现(例如,禁止写时复制),则为否,否则为是。会发生什么?

Should that work? Depending on how regex uses strings, if it does rely on new implementation (e.g. forbidden copy-on-write), then no, otherwise yes. What can happen? Anything.

在它的底部,您不应在任何使用post的新代码上使用 _GLIBCXX_USE_CXX11_ABI = 0 -c ++-03方言(即c ++-11、14、17等),因为它引入的实现与标准对象的新保证(特别是 std :: string

To the bottom of it, you should not use _GLIBCXX_USE_CXX11_ABI=0 on any new code that uses post-c++-03 dialect (i.e. c++-11,14,17,...), because it introduces implementations that are not compatible with the new guarantees on standard objects, particularly std::string.

我可以将 _GLIBCXX_USE_CXX11_ABI = 0 与std> = c ++-11一起使用吗? GCC开发人员要小心,您可以使用旧的ABI运行新的东西,这可能会使新功能与旧的共享库一起运行而受益。但是,这可能不是一个好主意,因为代码是在新标准中,但是标准库不符合该标准,以后可能会出现问题。您的问题就是一个例子。可以将两个ABI混合使用,在这里我们不起作用。

Can I use _GLIBCXX_USE_CXX11_ABI=0 with std>=c++-11? GCC developers took care that you can run new stuff with an old ABI, it benefits with a possibility of having new features running with old shared libraries. However that might not be a good idea, also because the code is in a new standard however the standard library does not conform to this standard, might turn out badly later. You problem is kind of an example of that. That you can by mix two ABI and here we are it is not working.

_GLIBCXX_USE_CXX11_ABI = 0 确实可用例如,如果您调用在某个.so库中定义的 foo(std :: string const&),并使用旧的ABI进行了编译。然后,在新的源文件中,您想使用旧的ABI编译该源。但是所有其他来源都将保留有新的ABI。

_GLIBCXX_USE_CXX11_ABI=0 is really usable if you call, for example, foo(std::string const&) defined in some .so library, compiled with an old ABI. Then in your new source file you would like to compile this source with an old ABI. But all other sources you would keep with a new ABI.


该问题在g ++ / libstdc ++的多个版本中都可以重现(我尝试了一些(从5.4到7.1)。 libc ++不会发生这种情况。

The problem is reproducible in several versions of g++/libstdc++ (I tried a few from 5.4 to 7.1). It doesn't occur with libc++.

libc ++ 不具有这种双重性,即单个 string 实现。

libc++ does not have this duality, i.e. single string implementation.

我没有给出此异常来自何处或原因的明确答案。我只能猜测有一些与 regex string 相关的共享全局资源ABI之间没有明确区分的语言环境。并且不同的ABI对其进行不同的处理会导致什么结果,例如异常,段故障,任何意外行为。恕我直言,我喜欢遵循上面提到的规则,这些规则最能反映 _GLIBCXX_USE_CXX11_ABI 和双重ABI的意图。

I do not give a clear answer where this exception is coming from or why. I only might guess that there is some shared global resource related to regex, string, or locale that is not distinguished clearly between ABIs. And different ABIs work with it differently what can result in anything, e.g. exception, segment fault, any unexpected behavior. IMHO, I prefer to stick with the rules, I mentioned above, that are most closely reflect the intent of _GLIBCXX_USE_CXX11_ABI and dual ABI.

这篇关于std :: regex和双重ABI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆