Фон
В прошлом году я использовал библиотеку nlohmann json [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/... располагаются в памяти (размеры/выравнивания данных)
- как работают вложенные вызовы функций (где и как хранится информация о том, как вернуться к вызывающему функции, где в регистре CPU и/или аргументы функции памяти передаются)
- как работает запуск/инициализация программы (какой формат данных имеет "исполняемый файл", как загружается код/данные, как работают DLL...)
Ответы на них следующие:
- (следовательно, у вас есть C ABI, C++ ABI, Fortran ABI, Pascal ABI... даже спецификация байт-кода Java, хотя таргетинг на "виртуальный" процессор вместо реального оборудования - это ABI)
- специфическая для операционной системы (MS Windows и Linux на одном и том же оборудовании используют другой ABI),
- аппаратное обеспечение/процессор (ARM и x86 ABI разные).
- (длинные) (существующие ABI часто обновлялись/обновлялись так, чтобы можно было использовать новые функции процессора, например, указать, как регистры SSE x86 будут использоваться приложениями, конечно, возможно только один раз У процессоров были эти регистры, поэтому существующие ABI необходимо было уточнить).
Таким образом, ABI является всеобъемлющим компонентом, а один из его компонентов (детали, специфичные для оборудования/ЦП) - это psABI.
Мой вопрос
Проблема, с которой я сталкиваюсь, - это
- Мне не нравятся универсальные отключения предупреждений, не понимая последствий.
- Совет "использование
-Wno-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 зафиксировал ошибку ABI [9], введенную в GCC 5, которая влияет на цели ARM.
- В примечаниях к выпуску указано, что "это изменение ABI". [10]
- По какой-то причине в примечаниях к выпуску указано, что связанные диагностические заметки генерируются при использовании недокументированного
-Wpsabi
, а не документально подтвержденного-Wabi
. - Это изменение ABI не упоминается в руководстве.
- Объединяя "это изменение ABI" и "используйте
-Wpsabi
", мне кажется, что это именно изменение psABI, а не другое изменение ABI. (В действительности это изменение в реализации GCC psABI, а не psABI)
Я знаю, что документация не всегда актуальна, особенно для того, что является известным недокументированным вариантом. Но я обеспокоен тем, что "использование -Wno-psabi
", по-видимому, является стандартным ответом на несколько разных типов этих загадочных диагностических заметок. Но, в моем основном понимании ABIs, не изменение ABI большое дело? Разве я не должен беспокоиться об изменении ABI, а не просто отбрасывать сообщение? Между недокументированным материалом и некоторыми более точными деталями ABI против psABI, я не совсем уверен...
Например, если я добавлю -Wno-psabi
в свой make файл, чтобы -Wno-psabi
эти заметки, что, если в будущем будет другое изменение ABI, которое повлияет на мой проект? Действительно ли я заставил замолчать будущие предупреждения или заметки, которые могут быть важны?
Кроме того, несмотря на то, что нам говорят: "Если вы перекомпилируете весь код, вам не о чем беспокоиться", [5] что такое "весь код"? Это мой исходный код? GLibC? Любая другая общедоступная библиотека в масштабе всей системы, которую я могу использовать?
Рекомендации
- https://github.com/nlohmann/json
- https://github.com/nlohmann/json/issues/658
- qaru.site/info/14949793/...
- qaru.site/info/1452703/...
- 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
- qaru.site/info/224888/...