_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