Понимание GCC 5 _GLIBCXX_USE_CXX11_ABI или нового ABI
https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html
Я столкнулся с проблемами с сбоем /valgrind с использованием std::string в GCC 5. В приведенной выше ссылке намечено, что в ABI запущен GCC 5.x. Новый ABI по умолчанию для libstd ++ - это С++ 11/14... который несовместим со старым ABI. Существует способ выбора старшего ABI с помощью определения.
Я пытаюсь понять, в чем разница между ABI и не нашел деталей. Я хотел бы помочь понять:
- Какие проблемы с std::string нужно исправлять, чтобы быть совместимыми с новым ABI? Связаны ли они с копией на запись?
- Изменит ли эти изменения его для более старого ABI?
- Любые советы по работе _GLIBCXX_USE_CXX11_ABI?
Подробнее о проблеме, с которой я столкнулся (https://github.com/YasserAsmi/jvar/issues/21) Проект отлично работал в GCC 4.8 и Clang. С GCC тот же код отказывается запускать:
x_misc(33112,0x7fff728c2000) malloc: *** error for object 0x7fd639c034cc: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
И вот частичный вывод Valgrind:
==33027== Invalid read of size 1
==33027== at 0x1006F78BA: _platform_memmove$VARIANT$Nehalem (in /usr/lib/system/libsystem_platform.dylib)
==33027== by 0x100009388: jvar::Variant::toString[abi:cxx11]() const (in bin/ex_misc)
==33027== by 0x1000023A7: bugreport() (in bin/ex_misc)
==33027== by 0x1000133B8: main (in bin/ex_misc)
В проекте используется std::string и имеет некоторое настраиваемое управление памятью. Он выполняет некоторые нестандартные, но действительные операции с использованием новых конструкторов размещения и т.д. Я стараюсь лучше понять, какой код выполняется API и как его исправить - место для запуска.
Ответы
Ответ 1
-
Старый std::string
не был совместим с С++ 11, поскольку этот стандарт запрещает реализацию копирования на запись. Не удалось создать совместимый std::string
без нарушения ABI, поэтому они сделали это, чтобы вернуться к несовместимой версии для совместимости с ABI.
-
Да.
-
Убедитесь, что все единицы перевода в вашей программе используют одно и то же значение _GLIBCXX_USE_CXX11_ABI
, и все должно быть в порядке. Если вы смешаете их с единицами перевода, у вас наверняка возникнут проблемы. Вы можете быть в порядке, если у вас разные значения определения в разных единицах перевода, которые не связывают string
друг с другом.
Ответ 2
Существует интересное различие между строкой COW и non-COW, например:
std::string some_string;
std::string foo()
{
return some_string;
}
char const *s = foo().c_str();
printf("%s\n",s);
Это будет работать с строками COW как c_str(), которые возвращаются some_string и foo указывают на одну и ту же память, но если это не COW, то s будет недействительным после уничтожения std::string, возвращаемого foo
.
Из примера там вы должны посмотреть в этом направлении.