「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > pthread を g++ に静的にリンクするとセグメンテーション違反が発生するのはなぜですか? `--whole-archive` オプションを使用して解決するにはどうすればよいですか?

pthread を g++ に静的にリンクするとセグメンテーション違反が発生するのはなぜですか? `--whole-archive` オプションを使用して解決するにはどうすればよいですか?

2024 年 11 月 15 日に公開
ブラウズ:900

Why does statically linking pthread with g   lead to a segmentation fault, and how can I resolve it using the `--whole-archive` option?

g が pthread を静的にリンクすると、セグメンテーション違反が発生します。なぜですか?

静的リンクでは、リンカーは最初のシンボルで停止します。それが弱いものであれば、強いものを探すのをやめる。 (動的にリンクされたライブラリの場合と同様に) すべてのシンボルを強制的に参照するには、ld は --whole-archive オプションをサポートしています。

次のコマンドが機能します:

g   -o one one.cpp -Wall -std=c  11 -O3 -static -pthread \
    -Wl,--whole-archive -lpthread -Wl,--no-whole-archive

何が起こっているかは次のとおりです:

  • -pthread は、pthread に対するリンクを意味します (およびプラットフォームでは、-D_REENTRANT などの追加のマクロが定義されています)。
  • -pthread が -lpthread へのリンクを暗黙的に指定する場合でも、静的にリンクするときに -lpthread を明示的に指定する必要があります。
  • Wl,-- Whole-archive は、必要なオブジェクト ファイルをアーカイブ内で検索するのではなく、リンカーにアーカイブ内のすべてのオブジェクト ファイルをリンクに含めるよう強制します。
  • Wl,--no-whole-archive は、後続のアーカイブ ファイル用の --whole-archive オプション。

弱いシンボルについて

ELF ファイル形式には、弱いシンボルと強いシンボルの概念があります。デフォルトでは、オブジェクト ファイル内のシンボルは強力です。リンク中に、強いシンボルは同じ名前の弱いシンボルをオーバーライドできます。

glibc と pthread の場合、弱いシンボルが使用されます。たとえば、fputc は POSIX でスレッドセーフであることが必要であり、同期する必要があるため、コストがかかります。シングルスレッド環境では、これらのコストを支払いたくありません。したがって、実装では同期関数を空のスタブとして実装し、関数を弱いシンボルとして宣言できます。

後で、マルチスレッド ライブラリがリンクされている場合 (pthread など)、シングルスレッドのサポートが明らかになります。意図されていません。マルチスレッド ライブラリをリンクする場合、リンカはスタブを実際の同期関数 (強力なシンボルとして定義され、スレッド ライブラリによって実装される) に置き換えることができます。

これをサンプル プログラムに適用します

libc.a ライブラリには __pthread_mutex_lock が弱いシンボルとして含まれており、libpthread.a ライブラリにはこれが強いシンボルとして含まれています。動的にリンクする場合、リンカーは弱いシンボルを強いシンボルに置き換えます。ただし、静的にリンクする場合は、同じセマンティクスを適用する必要があります。 -Wl,--whole-archive -lpthread -Wl,--no-whole-archive が必要なのはそのためです。

最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3