C/C++ コードを記述する場合、バイナリ実行可能ファイルをデバッグするには、コンパイラ/リンカーでデバッグ オプションを有効にする必要があります。GCC の場合、オプションは -g です。デバッグ オプションを有効にすると、バイナリ実行可能ファイルにどのような影響がありますか? デバッガーの機能を可能にするファイルには、どのような追加データが保存されますか?
7 に答える
-g は、シンボル テーブル情報を実行可能ファイルに格納するようにコンパイラに指示します。とりわけ、これには以下が含まれます。
- シンボル名
- シンボルのタイプ情報
- シンボルの元となったファイルと行番号
デバッガーはこの情報を使用して、シンボルの意味のある名前を出力し、命令をソース内の特定の行に関連付けます。
一部のコンパイラでは、-g を指定すると特定の最適化が無効になります。たとえば、明示的に -O[123] を指定しない限り、icc は -g を使用してデフォルトの最適化レベルを -O0 に設定します。また、-O[123] を指定しても、スタック トレースを防止する最適化は引き続き無効になります (たとえば、スタック フレームからフレーム ポインタを削除します。これはパフォーマンスにわずかな影響しか与えません)。
一部のコンパイラでは、 -g は、シンボルがどこから来たのかを混乱させる可能性のある最適化を無効にします (命令の並べ替え、ループの展開、インライン化など)。最適化してデバッグしたい場合は、gcc で -g3 を使用して、これを回避できます。インライン化された可能性のあるマクロ、展開、および関数に関する追加のデバッグ情報が含まれます。これにより、デバッガーとパフォーマンス ツールが最適化されたコードを元のソースにマップできるようになりますが、これはベスト エフォートです。一部の最適化は、実際にコードを台無しにします。
詳細については、DWARFをご覧ください。これは、もともと ELF (Linux およびその他の OS のバイナリ形式) に合わせて設計されたデバッグ形式です。
関数/変数名をデータの場所にマップするシンボル テーブルが実行可能ファイルに追加されるため、デバッガーは単なるポインターではなく、意味のある情報を報告できます。これはプログラムの速度に影響を与えず、'strip' コマンドでシンボル テーブルを削除できます。
デバッグおよびシンボル情報に加えて、
Google DWARF (ELF に関する開発者のジョーク)
デフォルトでは、デバッグが有効になっている場合、ほとんどのコンパイラの最適化はオフになっています。
したがって、コードは、リリース バイナリに適用される多くの高度に専門化された変換の結果ではなく、ソースをマシン コードに純粋に変換したものです。
しかし、最も重要な違い (私の意見では)
デバッグ ビルドのメモリは、通常、デバッグを容易にするためにコンパイラ固有の値に初期化されます。リリース ビルドでは、アプリケーション コードで明示的に行わない限り、メモリは初期化されません。
詳細については、コンパイラのドキュメントを確認してください。
ただし、DevStudio の例は次のとおりです。
- 0xCDCDCDCD ヒープに割り当てられているが、初期化されていない
- 0xDDDDDDDD 解放されたヒープ メモリ。
- 0xFDFDFDFD "NoMansLand" フェンスは、ヒープ メモリの境界に自動的に配置されます。決して上書きしてはいけません。1つを上書きすると、おそらく配列の最後から離れることになります。
- 0xCCCCCCCC スタックに割り当てられているが、初期化されていない
-g は、変数名、関数名、行番号などのデバッグ情報を実行可能ファイルに追加します。これにより、gdb などのデバッガーは、コードを 1 行ずつ実行し、ブレークポイントを設定し、変数の値を調べることができます。この追加情報のため、-g を使用すると実行可能ファイルのサイズが大きくなります。
また、gcc では、最適化をオンにする -O フラグと一緒に -g を使用できます。最適化された実行可能ファイルのデバッグは、変数が最適化されて取り除かれたり、命令が異なる順序で実行されたりする可能性があるため、非常に注意が必要です。一般に、-g を使用するときは最適化をオフにすることをお勧めしますが、コードが大幅に遅くなります。
興味深いことに、hexeditor をクラックして開き、hexeditor を使用して作成された実行可能ファイルとそうでない実行可能ファイルを確認-g
できます。シンボルや追加されたものを見ることができます。アセンブリ ( -S
) も変更される可能性がありますが、わかりません。
反対側からの問題をカバーするこの質問と重複する部分があります。
一部のオペレーティング システム ( z/OSなど) は、デバッグ シンボルを含む「サイド ファイル」を生成します。これにより、実行可能ファイルが余分な情報で肥大化するのを防ぐことができます。