Понимание 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.

Из примера там вы должны посмотреть в этом направлении.