web-dev-qa-db-ja.com

gcc -g:何が起こるか

この質問はインタビューで私に尋ねられました。

彼らは私がデバッグできるコアダンプファイルを生成する方法を私に尋ねました。それから私は-gフラグgccでできます。

それから彼らは私にそれを正確に何をするか尋ねた-gフラグはコンパイラーに対して行います。

私は、デバッグに使用できるコアファイル内のすべてのシンボルを開くと(おそらく間違った答え)言いました。

誰が正確に何をするのか教えてもらえますか?

41
Vijay

それは一種の権利ですが、不完全です。 _-g_は、コンパイラーとリンカーが実行可能ファイル自体にソースレベルのデバッグ/シンボル情報を生成して保持することを要求します。

If...

  • プログラムが後でクラッシュし、コアファイルを生成する(実際のコードに問題があることを示唆する)、または
  • 意図的なOSコマンドがそれを強制的にコアにしました(例:_kill -SIGQUIT_pid)、または
  • プログラムがコアをダンプする関数を呼び出します(例 abort

...- _-g_の使用によって実際に引き起こされるものはありません-デバッガーは、実行可能ファイルから「_-g_」シンボル情報を読み取り、コアと相互参照する方法を認識します。つまり、スタックフレーム内の変数と関数の適切な名前を確認し、行番号を取得し、実行可能ファイル内を歩き回るときにソースを確認できます。

このデバッグ情報は、コアから開始した場合でも実行可能ファイルのみで開始した場合でも、デバッグするときに役立ちます。 pstack のようなコマンドからより良い出力を生成するのに役立ちます。

ご使用の環境には、コアを生成するかどうかを制御する他の設定がある場合があります(コアは大きくなる場合があり、削除できるかどうか、いつ削除できるかを知る一般的な方法がないため、必ずしも必要ではありません)。たとえば、UNIX/LINUXシェルでは、多くの場合 _ulimit -c_ です。

[〜#〜] dwarf [〜#〜]Wikipedia -に埋め込まれたデバッグ/シンボル情報をエンコードするために一般的に使用されるデバッグ情報フォ​​ーマットについて読むこともできます。実行可能/ライブラリオブジェクト(UNIXおよびLinuxなど)。

コメントでビクターの要求ごとに更新...

シンボル情報は、ソースコードからの識別子をリストします(通常は name mangling が必要な場合のみ)、(仮想)メモリアドレス/プロセスメモリに読み込まれるオフセット、タイプ(データとコードなど)。例えば...

_$ cat ok.cc
int g_my_num;
namespace NS { int ns_my_num = 2; }
int f() { return g_my_num + NS::ns_my_num; }
int main() { return f(); }

$ g++ -g ok.cc -o ok    # compile ok executable with symbol info

$ nm ok    # show mangled identifiers
00000000004017c8 d _DYNAMIC
0000000000401960 d _GLOBAL_OFFSET_TABLE_
0000000000400478 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
000000000040037c T _Z1fv                     # this is f()
0000000000401798 D _ZN2NS9ns_my_numE         # this is NS::ns_my_num
00000000004017a8 d __CTOR_END__
00000000004017a0 d __CTOR_LIST__
00000000004017b8 d __DTOR_END__
00000000004017b0 d __DTOR_LIST__
0000000000400540 r __FRAME_END__
00000000004017c0 d __JCR_END__
00000000004017c0 d __JCR_LIST__
00000000004017c8 d __TMC_END__
00000000004017c8 d __TMC_LIST__
0000000000401980 A __bss_start
0000000000401788 D __data_start
0000000000400440 t __do_global_ctors_aux
00000000004002e0 t __do_global_dtors_aux
0000000000401790 d __dso_handle
0000000000000000 a __fini_array_end
0000000000000000 a __fini_array_start
                 w __gmon_start__
0000000000000000 a __init_array_end
0000000000000000 a __init_array_start
00000000004003a0 T __libc_csu_fini
00000000004003b0 T __libc_csu_init
                 U __libc_start_main
0000000000000000 a __preinit_array_end
0000000000000000 a __preinit_array_start
0000000000401980 A _edata
0000000000401994 A _end
0000000000400494 T _fini
000000000040047c T _init
0000000000400220 T _start
000000000040024c t call_gmon_start
0000000000401980 b completed.6118
0000000000401788 W data_start
0000000000400270 t deregister_tm_clones
0000000000401988 b dtor_idx.6120
0000000000401994 A end
0000000000400350 t frame_dummy
0000000000401990 B g_my_num                   # our global g_my_num
0000000000400390 T main                       # the int main() function
00000000004002a0 t register_tm_clones

$ nm ok | c++filt            # c++filt "unmangles" identifiers...
00000000004017c8 d _DYNAMIC
0000000000401960 d _GLOBAL_OFFSET_TABLE_
0000000000400478 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
000000000040037c T f()
0000000000401798 D NS::ns_my_num
00000000004017a8 d __CTOR_END__
00000000004017a0 d __CTOR_LIST__
00000000004017b8 d __DTOR_END__
00000000004017b0 d __DTOR_LIST__
0000000000400540 r __FRAME_END__
00000000004017c0 d __JCR_END__
00000000004017c0 d __JCR_LIST__
00000000004017c8 d __TMC_END__
00000000004017c8 d __TMC_LIST__
0000000000401980 A __bss_start
0000000000401788 D __data_start
0000000000400440 t __do_global_ctors_aux
00000000004002e0 t __do_global_dtors_aux
0000000000401790 d __dso_handle
0000000000000000 a __fini_array_end
0000000000000000 a __fini_array_start
                 w __gmon_start__
0000000000000000 a __init_array_end
0000000000000000 a __init_array_start
00000000004003a0 T __libc_csu_fini
00000000004003b0 T __libc_csu_init
                 U __libc_start_main
0000000000000000 a __preinit_array_end
0000000000000000 a __preinit_array_start
0000000000401980 A _edata
0000000000401994 A _end
0000000000400494 T _fini
000000000040047c T _init
0000000000400220 T _start
000000000040024c t call_gmon_start
0000000000401980 b completed.6118
0000000000401788 W data_start
0000000000400270 t deregister_tm_clones
0000000000401988 b dtor_idx.6120
0000000000401994 A end
0000000000400350 t frame_dummy
0000000000401990 B g_my_num
0000000000400390 T main
00000000004002a0 t register_tm_clones
_

ノート:

  • 関数f()main()T型です( "TEXT"を表します-実際にテキストまたは他のデータであるかどうかにかかわらず、読み取り専用の非ゼロメモリコンテンツに使用されます)または実行可能コード)、
  • _g_my_num_はBが暗黙的にゼロにされたメモリを持つグローバルである一方で、
  • _NS::ns_my_num_はDです。これは、実行可能ファイルがそのメモリを占有するために値_2_を明示的に提供する必要があるためです。

man/info-page for nm は、これらのことをさらに文書化します。..

50
Tony Delroy

-gフラグは、デバッグ情報を生成するようコンパイラーに指示します。コアファイルが生成されるかどうかには影響しません。ほとんどのUnixライクなシステムでは、ulimitコマンドを使用してセットアップできます。

9
Axel

Gcc -gフラグは、デバッグ情報を生成して埋め込むようにgccに指示します。 ulimit -cは、コアファイル生成を有効にするために使用されます。これらのいずれかをもう一方なしで使用できます。

5
Erik

-gは、デバッグ情報(変数名、行番号など)を実行可能ファイルに追加します。これは、コアファイルを理解するために必要なことの一部です。

http://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html#Debugging-Options

3
JeremyP

-gフラグを付けないと、gdbのlistを呼び出してソースコードがどのように見えるかをリストできません。 「シンボルテーブルがロードされていません。「ファイル」コマンドを使用してください。」と表示されます。

また、info funcまたはinfo frame、gdbのinfo localsを-gなしで入力すると、戻りデータ型とその引数は表示されず、基本的に命令の変数への変換は行われません(シンボルテーブルからのマッピング)。

1
Steven Wong

コアダンプは、このプロセスがシグナルを受信したときのプロセスのデフォルトアクションの1つです。標準シグナル「SIGQUIT」、「SIGILL」、「SIGABRT」、「SIGFPE」、「SIGSEGV」ただし、ほとんどのシェルはコアファイルの作成を抑制します。これは、コアファイルが大きくなる傾向があり、ある程度の時間または多くの時間がかかるためです。

コア生成を有効にするために、「ulimit」は、シェルまたはその子プロセスのファイル制限を設定するために使用できるユーティリティです。

コンパイラフラグ "-g"またはコンパイラのみに関係するもの。論理的には、コアダンプとは関係ありません。

1
pepero

コアファイルは、セグメンテーションフォールトまたはそのような例外で生成されます。 gdb source.cc coreは、コアファイルを調べる1つの方法です。バックトレースとすべてのフレームの調査は、コアの調査から始まります。 -gは、デバッグシンボルをバイナリに追加します。

1
vpit3833