_GLIBCXX_USE_CXX11_ABI 在 RHEL6 和 RHEL7 上禁用?

Posted

技术标签:

【中文标题】_GLIBCXX_USE_CXX11_ABI 在 RHEL6 和 RHEL7 上禁用?【英文标题】:_GLIBCXX_USE_CXX11_ABI disabled on RHEL6 and RHEL7? 【发布时间】:2018-11-22 23:19:07 【问题描述】:

我在 RHEL6 和 RHEL7 上安装了 gcc 5.2.1,看起来 _GLIBCXX_USE_CXX11_ABI 被禁用了。即使我手动运行-D_GLIBCXX_USE_CXX11_ABI=1 -std=c++14,它也不起作用。这意味着我不会获得小字符串优化功能。例如,以下代码的输出总是有 8 和 'micro not set'。对于 SSO,如果我们查看 code bits/basic_string.h,std::string 的大小应该至少为 16。有什么解决方法吗?

#include <string>
#include <iostream>

int main()

    std::cout << sizeof(std::string) << std::endl;

#if _GLIBCXX_USE_CXX11_ABI
    std::cout << "macro set" << std::endl;
#else
    std::cout << "macro not set" << std::endl;
#endif


【问题讨论】:

定义“不按预期工作”?请注意,1 是该宏的默认值。 你的 GCC 是从哪里安装的? Gcc 是坚定的。假设它是 RHEL 发行版的一部分? Feature, not a bug. 您使用的是不支持新 ABI 的 devtoolset 版本的 GCC。我将更改问题上的标签以说明这一点,因为这就是您看到的行为的原因。 【参考方案1】:

bugzilla.redhat有以下回复

Jakub Jelinek 2018-02-19 06:08:00 EST

我们已经尽力了,但无法支持这一点,在 RHEL6 也不在 RHEL7 上,这就是它被强制禁用的原因。它会 在 RHEL8 中工作(并且也是那里的默认值)。

【讨论】:

【参考方案2】:

这取决于您的libstdc++ 版本,请确保您的包含/链接/运行时路径正确。在您的系统中搜索该宏,然后使用该宏,只需确保链接到正确的 stdlib/abi 库即可。

如果您没有它,您可以随时自己构建它,但请注意,如果您拥有的其余程序使用旧 ABI,它们将无法与您的新 libstdc++ 一起使用。


编辑: 考虑到这一点,您是否为g++ 指定了正确的-std= 标志?你试过-std=gnu11吗?它可能像那样微不足道。如果没有,请继续阅读。不要手动指定该定义,您将破坏 ABI 与 libstdc++ 的兼容性,从而导致级联的奇妙崩溃。只有在自己构建标准库时才能指定此类内容。


剩下的内容有点矫枉过正,但它解释了如何构建和/或选择您想要使用的标准库。

在使用libc++ 的第 2 版 ABI 时,我遇到了类似的问题,其中链接到它的所有内容都必须使用正确的标头和正确的 ABI 重新构建(例如小字符串优化就是其中之一)。

例如,在构建 C++ 对象时,我使用以下标志来指定自定义 stdlib 标头路径的位置,而不是使用操作系统提供的路径(我使用 Clang,但原理相似):

-nostdinc++ -I/usr/local/sdk/llvm.6.0.1/include/c++/v1/

然后在链接阶段,我使用$ORIGIN 相对运行时搜索路径,因为在生产机器上,标准库安装在更合理的位置,但您可以为任何您想要的 stdlib 指定一个固定的。您还需要确保链接器可以在与-L 进行静态链接期间找到适当的标准库。

-Wl,-rpath,'$ORIGIN/../lib' -L/usr/local/sdk/llvm.6.0.1/lib

您需要链接-lstdc++-lsupc++(如果是静态链接,顺序很重要),只要您提供正确的库搜索路径,静态链接器应该会找到它们是 GCC/GNU C++ 标准库和 ABI 支持库。

当心,如果你用这个替换你的系统 libstdc+ 任何与旧 ABI 布局链接的程序如果动态链接的话都会中断,所以要小心。

【讨论】:

但是我的“宏集”代码应该和libstdc++无关吧? 试过 g++ -D_GLIBCXX_USE_CXX11_ABI=1 -std=c++14 g++ -D_GLIBCXX_USE_CXX11_ABI=1 -std=gnu++14 和'-D'。我们的测试显示“未设置宏”。 标头(至少在 libc++ 上)暴露了结构布局等 ABI 细节,通过更改它们并与它们一起构建,您实际上是在链接不兼容的 stdlib,因为它不仅仅是标头,它具有相当一些期望布局相同的编译部分。您可以构建自己的标准库,但您将破坏与操作系统标准库链接的每个 C++ 共享对象的 ABI 兼容性。 这个答案相当具有误导性。没有-std 选项会改变ABI,并且libstdc++ 中的新ABI 并没有使所有对象和库不兼容,这就是库SONAME 没有改变的原因。有关详细信息,请参阅gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html

以上是关于_GLIBCXX_USE_CXX11_ABI 在 RHEL6 和 RHEL7 上禁用?的主要内容,如果未能解决你的问题,请参考以下文章

GCC编译宏_GLIBCXX_USE_CXX11_ABI背景分析和实现原理

GCC编译宏_GLIBCXX_USE_CXX11_ABI背景分析和实现原理

将程序链接到库,每个库使用不同的 _GLIBCXX_USE_CXX11_ABI

Debian Buster 中的库不匹配?

使用 -D_GLIBCXX_USE_CXX11_ABI=0 构建提升

c++ 项目仍然需要 -D_GLIBCXX_USE_CXX11_ABI=0