昨年は、nlohmann jsonライブラリを使用していました[1] また、警告なしでGCC 5.x _arm-linux-gnueabi-*
_を使用してx86_64でクロスコンパイルしていました。 GCCを新しいバージョンに更新すると、GCCは暗号化された診断メモのページを生成します。たとえば、ここにメモの1つがあります
_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)は、高レベル言語の低レベル概念と特定のハードウェア/ OSプラットフォームのマシンコードの能力。次のようなものが含まれます。
- c/C++/Fortran/...データ型がメモリにどのように配置されるか(データサイズ/アライメント)
- ネストされた関数呼び出しがどのように機能するか(関数の呼び出し元に戻る方法に関する情報が保存されている場所と方法、CPUレジスタ内および/またはメモリ内の場所)関数の引数が渡されます)
- どのようにプログラムの起動/初期化が機能するか(「実行可能ファイル」のデータ形式、そこからコード/データがロードされる方法、DLLが機能する方法... )
これらに対する答えは次のとおりです。
- 言語固有(C ABI、C++ ABI、Fortran ABI、Pascal ABI、... Javaバイトコード仕様もありますが、「仮想」実際のハードウェアの代わりにプロセッサはABIです)、
- オペレーティングシステム固有(同じハードウェア上のMS WindowsとLinuxは異なるABIを使用します)、
- ハードウェア/ CPU固有(ARMとx86 ABIは異なります)。
- (長い)時間をかけて進化する(既存のABIは、たとえばx86 SSEの指定方法など、新しいCPU機能を利用できるように頻繁に更新/改訂されています。レジスタがアプリで使用されるのはもちろん、CPU hadこれらのregであるため、既存のABIを明確にする必要がある場合のみ可能です。
したがって、ABIは包括的なコンポーネントであり、そのコンポーネントの1つ(「ハードウェア/ CPU固有の」詳細)はpsABIです。
私が抱えている問題は
-Wno-psabi
_を使用してノートを消す」というアドバイスは、コンパイラのアップグレード後に「突然表示される」これらのタイプの診断ノートのかなり一般的なアドバイスのようです。[2][3][4] GCC開発者の1人でさえ、これを行うことを提案しています。[5]-Wpsabi
_も_-Wno-psabi
_も文書化されていません[6] GCCマニュアルで。[7]その結果、_-Wno-psabi
_が正確に何に影響するのか、そして何が影響しないのかは本当にわかりません。関連オプション_-Wabi
_ is文書化:[8]
-Wabi (C, Objective-C, C++ and Objective-C++ only)
G ++がベンダーに中立なC++ ABIと互換性のないコードを生成する場合に警告する...
また、psABI関連の変更についても警告します。この時点での既知のpsABIの変更は次のとおりです。
- SysV/x86-64の場合、long doubleメンバーを持つ共用体は、psABIで指定されているようにメモリに渡されます。例えば:
_
union U {
_ _long double ld;
_ _int i;
_ _};
__
union U
_は常にメモリに渡されます。
このすべての私の理解は
-Wabi
_は、psABIが変更されたときに警告を生成します。-Wpsabi
_ではなく、ドキュメント化されていない_-Wabi
_を使用すると、関連する診断ノートが生成されると記載されています。-Wpsabi
_を使用」をまとめると、これは具体的に psABIの変更であり、異なる種類のABIの変更ではないようです。 (実際には、psABI自体ではなく、GCCのpsABIの実装の変更です)特に文書化されていないオプションとして知られているものについては、文書化が常に最新とは限らないことを知っています。しかし、私の懸念は、「use _-Wno-psabi
_」がこれらの不可解な診断メモのいくつかの異なる種類の標準的な応答であるように見えることです。しかし、ABIについての私の基本的な理解では、ABIは大きな変化ではないでしょうか?メッセージを消すのではなく、ABIの変更を心配するべきではありませんか?文書化されていないものと、ABI vs psABIの詳細のいくつかとの間で、私は本当に確信がありません...
たとえば、_-Wno-psabi
_をメイクファイルに追加してそれらのメモを消した場合、将来的にdoesがプロジェクトに影響する別のABIの変更があるとどうなりますか?重要な可能性のある将来の警告またはメモを効果的に黙らせましたか?
また、「すべてのコードを再コンパイルしても心配する必要はありません」と言われても、[5] 「すべてのコード」とは正確には何ですか?それは私のソースコードですか? glibc?私が使用している他のシステム全体の共有ライブラリはありますか?
ライブラリの境界を越える場合にのみ、ABIについて心配する必要があります。おそらくすべてのオブジェクトファイルが同じコンパイラバージョンとスイッチでコンパイルされているため、独自のアプリケーション/ライブラリ内では、ABIは実際には重要ではありません。
ABI1でコンパイルされたライブラリとABI2でコンパイルされたアプリケーションがある場合、引数を正しく渡さないため、ライブラリから関数を呼び出そうとするとアプリケーションがクラッシュします。クラッシュを修正するには、ライブラリ(および依存する他のライブラリ)をABI2で再コンパイルする必要があります。
特定のケースでは、アプリケーションと同じコンパイラバージョンでnlohmannをコンパイルする(またはヘッダーとしてnlohmannを使用している)限り、ABIの変更を心配する必要はありません。
警告をグローバルに抑制することは、将来のABIの問題が発生するのを防ぐため、危険なオプションのようです。より良いオプションは、#pragma
を使用して、問題の関数だけの警告を無効にすることです。例:
#pragma GCC diagnostic Push
#pragma GCC diagnostic ignored "-Wno-psabi"
void foo()
{
}
#pragma GCC diagnostic pop