У меня есть gcc 5.2.1 на RHEL6 и RHEL7, и похоже, что _GLIBCXX_USE_CXX11_ABI отключается. Это не работает, даже если я запускаю вручную -D_GLIBCXX_USE_CXX11_ABI=1 -std=c++14
, Это означает, что я не получу небольшую функцию оптимизации строк. Например, вывод следующего кода всегда имеет 8 и «микро не установлено». Для SSO размер std :: string должен быть не менее 16, если мы посмотрим на код биты / basic_string.h. Любое решение?
#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
}
bugzilla.redhat имеет ответ ниже
Якуб Елинек 2018-02-19 06:08:00 EST
Мы очень старались, но это невозможно поддержать, ни на
RHEL6 или RHEL7, поэтому он принудительно отключен. Будет
работать в RHEL8 (и быть там по умолчанию).
Это будет зависеть от вашего libstdc++
версия, убедитесь, что ваши пути include / link / runtime правильные. Найдите в вашей системе этот макрос, а затем используйте его, просто убедитесь, что вы ссылаетесь на правильные библиотеки stdlib / abi.
Если у вас его нет, вы всегда можете создать его самостоятельно, однако помните, что если остальные программы, которые у вас есть, используют старый ABI, они не будут работать с вашим новым libstdc++
,
Редактировать: Думая об этом, вы указали правильный -std=
флаг для g++
? Ты пытался -std=gnu11
? Это может быть так же тривиально, как это. Если нет, то читайте дальше. Не указывайте это вручную, вы нарушите совместимость ABI с вашим libstdc++
приводя к каскадам чудесных аварий. Единственный раз, когда вы можете указать такие вещи, это когда вы создаете stdlib самостоятельно.
В остальном это немного излишне, но объясняет, как собрать и / или выбрать, какой stdlib вы хотите использовать.
У меня похожая проблема при использовании версии 2 ABI libc++
где все, что связывается с ним, должно быть перестроено с правильными заголовками и, следовательно, с правильным 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 ++ stdlib и ABI.
Остерегайтесь, если вы замените свою систему libstdc + на это, любые программы, связанные со старым макетом ABI, сломаются, если они динамически связаны, поэтому будьте осторожны