[解決済み] GCCの-Wpsabiオプションはいったい何をするのでしょうか? それを抑制することの意味は何ですか?
質問
背景
昨年は nlohmann json library を使っていました。
[1]
を使用しており、GCC 5.x を使用して x86_64 でクロスコンパイルしていました。
arm-linux-gnueabi-*
を使用して、警告なしでクロスコンパイルしていました。私が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]
Application Binary Interfaces (ABI) と processor-specific ABI (psABI) の基本は理解できたのですが、どのようにすればよいのでしょうか。参考までに、この回答
[11] が ABI の簡単な概要を説明しています。
ABI ( アプリケーションバイナリインターフェース ) は、高級言語における低レベルの概念と、特定のハードウェア/OS プラットフォームのマシンコードの能力との間のマッピングを定義した規格です。以下のようなものが含まれます。
- どのように C/C++/Fortran/... データ型 がメモリ上にどのように配置されるか(データサイズ/アラインメント)。
- どのようにネストされた 関数呼び出し の動作(関数の呼び出し元に戻るための情報がどこに、どのように格納されているか、CPUのレジスタやメモリ内の関数引数がどこに渡されているか)。
- どのように プログラムの起動/初期化 がどのように動作するか(実行ファイルがどのようなデータ形式を持っているか、そこからどのようにコードやデータがロードされるか、DLLがどのように動作するか......)。
これらに対する回答は
- 言語固有 (従って、C ABI、C++ ABI、Fortran ABI、Pascal ABI、...さらに Java バイトコード仕様も、実際のハードウェアではなく "virtual" プロセッサをターゲットにしているものの、ABI です) 。
- オペレーティング システム固有 (同じハードウェア上の MS Windows と Linux は異なる ABI を使用します)。
- ハードウェア/CPU 固有の (ARM と x86 の ABI は異なります)。
- 長い)時間をかけて進化している (既存の ABI は、新しい CPU の機能を利用できるようにしばしば更新/改訂されてきました。たとえば、x86 SSE レジスタをアプリケーションで使用する方法を指定することは、当然ながら CPU が が持っていた このため、既存の ABI は明確にされる必要がありました)。
つまり、ABI は包括的なコンポーネントであり、そのコンポーネントの 1 つ ("hardware/CPU-specific" 詳細) が 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 では、long double のメンバーを持つユニオンは 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の変更ではありません。(実際には、psABI 自体ではなく、psABI の GCC の実装における変更です)。
ドキュメントが常に最新ではないこと、特に、既知のドキュメント化されていないオプションであるものについてはそうであることは分かっています。しかし、私が懸念しているのは、"use
-Wno-psabi
は、これらの不可解な診断メモのいくつかの異なる種類の標準的な応答のようです。しかし、私の ABI に関する基本的な理解では、ABI の変更は大きな問題ではないのでしょうか?メッセージを消すのではなく、ABIの変更に関心を持つべきではないでしょうか?文書化されていないものと、ABI 対 psABI の細かい部分との間で、私はよく分からないのですが......。
例えば、もし私が
-Wno-psabi
を追加し、これらのノートを消した場合、将来的に別の 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
どのように解決するのですか?
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
関連
-
[解決済み】非静的メンバ関数への参照を呼び出す必要がある
-
[解決済み】Visual Studio 2015で「非標準の構文。'&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み】「std::operator」で「operator<<」にマッチするものがない。
-
[解決済み】VC++の致命的なエラーLNK1168:書き込みのためにfilename.exeを開くことができません。
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] ルール・オブ・スリーとは?
-
[解決済み] コピーアンドスワップ慣用句とは?
-
[解決済み] Cプリプロセッサはなぜ "linux "という単語を定数 "1 "と解釈するのですか?
-
[解決済み】C/C++の"-->"演算子とは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++ 非推奨の文字列定数から「char*」への変換について
-
[解決済み] error: 'ostream' does not name a type.
-
[解決済み】C++コンパイルタイムエラー:数値定数の前に期待される識別子
-
[解決済み】浮動小数点例外エラーが発生する: 8
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み】VC++の致命的なエラーLNK1168:書き込みのためにfilename.exeを開くことができません。
-
[解決済み] 警告:暗黙の定数変換でのオーバーフロー
-
[解決済み】'std::cout'への未定義の参照
-
[解決済み] ARM ABIとEABIの目的は何ですか?