Фон
В прошлом году я использовал 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
Источник: