Фон
В прошлом году я использовал json-библиотеку nlohmann [1] и выполнял кросс-компиляцию на x86_64 с использованием GCC 5.x arm-linux-gnueabi-*
без предупреждений. Когда я обновлял GCC до более новой версии, GCC генерировал страницы загадочных диагностических заметок. Например, вот одна из заметок
In file included from /usr/arm-linux-gnueabi/include/c++/7/vector:69:0,
from include/json.hpp:58,
from src/write_hsi.cpp:23:
/usr/arm-linux-gnueabi/include/c++/7/bits/vector.tcc: In member function ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long long int, long long unsigned int, double, std::allocator, nlohmann::adl_serializer>}; _Tp = nlohmann::basic_json<>; _Alloc = std::allocator<nlohmann::basic_json<> >]’:
/usr/arm-linux-gnueabi/include/c++/7/bits/vector.tcc:394:7: note: parameter passing for argument of type ‘std::vector<nlohmann::basic_json<>, std::allocator<nlohmann::basic_json<> > >::iterator {aka __gnu_cxx::__normal_iterator<nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<>, std::allocator<nlohmann::basic_json<> > > >}’ changed in GCC 7.1
vector<_Tp, _Alloc>::
^~~~~~~~~~~~~~~~~~~
/usr/arm-linux-gnueabi/include/c++/7/bits/vector.tcc: In member function ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer> nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::parser::parse_internal(bool) [with ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’:
/usr/arm-linux-gnueabi/include/c++/7/bits/vector.tcc:105:21: note: parameter passing for argument of type ‘__gnu_cxx::__normal_iterator<nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<>, std::allocator<nlohmann::basic_json<> > > >’ changed in GCC 7.1
_M_realloc_insert(end(), std::forward<_Args>(__args)...);
~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Решение было легко найти, а именно добавлением -Wno-psabi
к параметрам компилятора. Фактически, это было исправление, реализованное в библиотеке. [2]
Я понимаю основы двоичных интерфейсов приложений (ABI) и ABI для конкретных процессоров (psABI). Для справки, этот ответ [11] дает краткий обзор ABI:
ABI (Application Binary Interface) — это стандарт, который определяет соответствие между низкоуровневыми концепциями языков высокого уровня и возможностями машинного кода конкретной аппаратной платформы / платформы ОС. . Сюда входят такие вещи, как:
- как C / C ++ / Fortran / … типы данных размещаются в памяти (размеры данных / выравнивание)
- как работают вложенные вызовы функций (где и как хранится информация о том, как вернуться к вызывающему функцию, где в регистрах ЦП и / или в памяти передаются аргументы функции)
- как работает запуск / инициализация программы (какой формат данных имеет «исполняемый файл», как код / данные загружаются оттуда, как работают библиотеки DLL …)
Ответы на них следующие:
- зависящий от языка (следовательно, у вас есть C ABI, C ++ ABI, Fortran ABI, Pascal ABI … даже спецификация байт-кода Java, хотя нацелена на «виртуальный» процессор вместо реального оборудования, является ABI),
- зависит от операционной системы (MS Windows и Linux на одном оборудовании используют другой ABI),
- зависит от оборудования / процессора (ABI для ARM и x86 различаются).
- эволюционирует в течение (долгого) времени (существующие ABI часто обновлялись / редактировались, чтобы можно было использовать новые функции ЦП, например, указание, как регистры x86 SSE должны использоваться apps, конечно, было возможно только тогда, когда процессоры имели эти регистры, поэтому существующие ABI нуждались в уточнении).
Таким образом, ABI — это всеобъемлющий компонент, а одним из его компонентов (детали, относящиеся к «аппаратному обеспечению / ЦП») является psABI.
Моя проблема
У меня проблема
- Мне не нравится отключение предупреждений без понимания последствий.
- Совет «используйте
-Wno-psabi
, чтобы убрать заметки» кажется довольно распространенным советом для этих типов диагностических заметок, которые «внезапно появляются» после обновления компилятора. [2] [3] [4] Даже один из разработчиков GCC предлагает сделать это. [5] - Ни
-Wpsabi
, ни-Wno-psabi
не задокументированы [6] в руководстве GCC. [7]
В результате я не совсем уверен, что именно -Wno-psabi
повлияет и не повлияет. Связанный вариант -Wabi
задокументирован: [8]
-Wabi (C, Objective-C, C++ and Objective-C++ only)
Предупреждать, когда G ++ генерирует код, который, вероятно, несовместим с независимым от поставщика C ++ ABI …
Он также предупреждает об изменениях, связанных с psABI. К известным изменениям psABI на данный момент относятся:
- Для SysV / x86-64 объединения с длинными двойными членами передаются в память, как указано в psABI. Например:
union U {
long double ld;
int i;
};
union U
всегда передается в памяти.
Мое понимание всего этого
-Wabi
будет генерировать предупреждения при изменении psABI.- GCC 7 fixed an ABI bug[9] introduced in GCC 5 that affects ARM targets.
- In the release notes it is stated «this is an ABI change.»[10]
- По какой-то причине в примечаниях к выпуску указано, что соответствующие диагностические примечания создаются при использовании недокументированного
-Wpsabi
, а не документированного-Wabi
. - Это изменение ABI не упоминается в руководстве.
- Если сложить вместе «это изменение ABI» и «использовать
-Wpsabi
», мне кажется, что это конкретно изменение psABI, а не другой вид изменения ABI. (На самом деле это изменение в реализации psABI в GCC, а не в самом psABI)
Я знаю, что документация не всегда актуальна, особенно для того, что является известным недокументированным вариантом. Но меня беспокоит то, что «use -Wno-psabi
» кажется стандартным ответом на несколько различных типов этих загадочных диагностических заметок. Но в моем базовом понимании ABI, разве ABI не меняет большого дела? Разве меня не должно беспокоить изменение ABI, а не просто убрать сообщение? Между недокументированным материалом и некоторыми более тонкими деталями ABI vs psABI, я не совсем уверен …
Например, если я добавлю -Wno-psabi
в свой make-файл, чтобы убрать эти заметки, что, если в будущем произойдет еще одно изменение ABI, которое повлияет на мой проект? Эффективно ли я заглушил будущие предупреждения или заметки, которые могут быть важны?
Кроме того, даже несмотря на то, что нам говорят «если вы перекомпилируете весь код, не о чем беспокоиться», [5] что именно такое «весь код»? Это мой исходный код? glibc? Любую другую общесистемную общую библиотеку, которую я мог бы использовать?
использованная литература
- https://github.com/nlohmann/json
- https://github.com/nlohmann/json/issues/658
- https://stackoverflow.com/a/48149400
- https://stackoverflow.com/a/13915796/10270632
- https://gcc.gnu.org/ml/gcc/2017-05/msg00073.html
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81831
- https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc
- https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/C_002b_002b-Dialect-Options.html
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77728
- https://gcc.gnu.org/gcc-7/changes.html
- https://stackoverflow.com/a/8063350
Освежающий хороший вопрос; проголосовать за. — person rmc schedule 25.08.2018
@ jesper-juhl Спасибо. Я просмотрел SO, списки рассылки и т. Д. В поисках ответа. Я даже потратил немного времени на исходный код GCC, пытаясь понять это (и, возможно, смогу внести исправление, чтобы исправить отсутствующая документация), но я не был достаточно знаком с внутренним устройством GCC, чтобы понять это. Такое чувство, что забить гвоздь кувалдой, а потом забыть, что нормальные молотки существуют … — person rmc schedule 25.08.2018
Мне просто грустно, что у меня нет для тебя хорошего ответа. Но, надеюсь, кто-нибудь зайдет, кто это сделает. — person rmc schedule 25.08.2018
@ jesper-juhl Это делает нас двоих Я думаю, что когда-нибудь у меня возникнет вопрос, на который еще не было ответа SO, и я был бы вынужден создать учетную запись, чтобы спросить об этом. — person rmc schedule 25.08.2018
Я не думаю, что это повлияет на вас. Если стандартная библиотека скомпилирована с той же версией GCC (я имею в виду версию, использующую тот же abi), которую вы используете (что вполне вероятно), все должно быть в порядке. — person rmc schedule 25.08.2018
@geza Я не думаю, что стандартная библиотека принадлежит той же версии GCC. Эти сообщения появились, когда я обновил кросс-компилятор на главном компьютере x86_64. На целевой машине ARM установлен GCC 5.x. Я предполагаю, что это оставит мне выбор между переустановкой кросс-компилятора GCC 5.x, компиляцией на целевой машине, статической связью всего или поиском способа обновления пакетов на целевой машине, не подключенной к сети. . Кроме того, даже если это не проблема, я все равно хотел бы выяснить, на что влияет -Wpsabi
(первая часть вопроса). — person rmc schedule 25.08.2018
Poreferrer Дополнение ABI — поучительна глава «Введение». Я предполагаю, что изменения ABI или изменения PS ABI обрабатываются одинаково, но имеют два разных флага компилятора для подавления. Документы для -Wabi
должны применяться также для _2 _ / _ 3_, где последнее относится к изменениям, связанным с соответствием PS ABI, а не ABI. — person rmc schedule 26.08.2018
@rmc: А. Как-то я предположил, что вы нацеливаетесь на андроид. Обратите внимание: вполне вероятно, что приведенные вами предупреждения не причинят никакого вреда. Это шаблонный код, который включается в elf. Таким образом, между вашим кодом и скомпилированным libstdc ++ не будет несоответствия ABI. Но, конечно, вам нужно будет проверить все предупреждения, потому что, возможно, там есть что-то, что может быть потенциально плохим (вам, конечно, нужно перекомпилировать json-библиотеку nlohmann с новым компилятором). — person rmc schedule 26.08.2018
Ссылаясь на System V ABI: Сегодня это стандартный ABI, используемый основными операционными системами Unix. .. ABI организован как переносимый базовый документ и приложения для конкретных платформ, которые заполняют пустые пробелы … Были опубликованы неофициальные дополнения к процессорам новой архитектуры, поскольку формат был адаптирован для новых платформ. .. Из-за множества неофициальных спецификаций дополнений и хаотичной истории операционных систем Unix … ABI хорошо понимают обычные инструменты разработки операционных систем, такие как Binutils и GCC. — person rmc schedule 26.08.2018
Вы используете nlohmann только через заголовок, а не как архив библиотеки или совместно используемый объект? — person rmc schedule 27.08.2018
Возможно, это связано с исправлением ошибок GCC. Вот новый экземпляр: gcc.gnu.org/gcc-9/changes.html < / а>. — person rmc schedule 16.03.2020
@Peter, да, мы использовали nlohmann только как заголовок — person rmc schedule 08.03.2021
@FrankHB Я думаю, это на самом деле иллюстрирует именно ту ситуацию, о которой я беспокоился, если бы отключил -Wpsabi
. Предупреждение об изменении ABI, которое я обнаружил, появилось после обновления GCC 5.x до более новой версии (я не могу вспомнить, была ли это более новая версия 5.x или 6.x). Связанные вами изменения GCC 9 связаны с ошибкой On Arm … в выпусках GCC 6, 7 и 8 … Это изменение ABI. Если опция -Wpsabi включена … компилятор выдаст диагностическое сообщение … Если бы я поместил -Wno-psabi в свой make-файл 2 года назад при использовании GCC 5.x, он бы подавил предупреждения на этом более позднем ABI изменение. — person rmc schedule 08.03.2021
Вам нужно беспокоиться об ABI только тогда, когда вы пересекаете границы библиотеки. В ваших собственных приложениях / библиотеках ABI на самом деле не имеет значения, поскольку, по-видимому, все ваши объектные файлы скомпилированы с одной и той же версией компилятора и переключателями.
Если у вас есть библиотека, скомпилированная с помощью ABI1, и приложение, скомпилированное с помощью ABI2, тогда приложение выйдет из строя, когда оно попытается вызвать функции из библиотеки, поскольку оно не будет передавать аргументы правильно. Чтобы исправить сбой, вам нужно будет перекомпилировать библиотеку (и любые другие библиотеки, от которых она зависит) с ABI2.
В вашем конкретном случае, если вы компилируете nlohmann с той же версией компилятора, что и ваше приложение (или просто используете nlohmann в качестве заголовка), вам не нужно беспокоиться об изменении ABI.
Глобальное подавление предупреждения кажется опасным вариантом, поскольку оно не позволит вам увидеть какие-либо проблемы с ABI в будущем. Лучшим вариантом было бы использовать
#pragma
, чтобы отключить предупреждение только для рассматриваемых функций, например:Извините, что вернул к жизни очень старый пост, но вы говорите, что при вызове библиотеки, скомпилированной в ABI1, из приложения, скомпилированного с помощью ABI2, произойдет сбой приложения, это гарантированное поведение или вы используете термин сбой в качестве общего термина для описания приложения будет плохо себя вести. Взяв конкретный пример Redhat, они просто говорят, что он не поддерживается и не гарантированно работает, а не о том, что он выйдет из строя. Честно говоря, я бы предпочел крах, но хотел бы понять, откуда взялось это утверждение. — person rmc; 24.11.2020
Да, нет гарантии, что произойдет сбой, поведение будет неопределенным — person rmc; 24.11.2020
undefined — опасная зона, она может дать неосторожным людям ложное чувство безопасности, когда все выглядит хорошо, а затем когда в ней все разваливается. Скорее приложение не запускается, и проблема решается — person rmc; 25.11.2020
@ alan-birtles Вау, я не заходил в систему много лет и забыл, что даже задал этот вопрос. Я собираюсь отметить ваш ответ как принятый, так как я думаю, что он соответствует всем пунктам, которые меня интересовали. IIRC, поскольку это было для встроенной цели и у нас были исходники для всех сторонних библиотек, мы просто перекомпилировали все с помощью обновленного кросс-компилятора. — person rmc; 08.03.2021
-Wno-psabi не распознается диагностической прагмой gcc для меня. Код не будет построен с этой строкой в нем. — person rmc; 05.05.2021