2016-11-07 4 views
3

私が書いているコードでGDBを使ってsegfaultのトラブルシューティングを試みていました。 backtraceコマンドを使用すると、GDBは行番号や関数名を表示しません。ここに私の問題を示して短いサンプルプログラムです:GDBで行番号や関数名が表示されないのはなぜですか?

void segfault(int *b) { 
    // This causes a segfault on CentOS7 Intel 64-bit 
    b[-1] = 5; 
} 

void main() { 
    int a[10]; 
    segfault(a); 
} 

しかし、私は

gcc -ggdb -O0 test.c -o segfaulttest 

そして、私は、GDBのバックトレースコマンドを使用するときに、それを実行するためにgdb segfaulttestを使用してコンパイルするとき、私は任意の行番号を得ることはありませんまたは関数名。トレースにmain()segfault()と表示されると思います。

私が使用している

Reading symbols from /home/user/test/segfaulttest...done. 
(gdb) run 
Starting program: /home/user/test/segfaulttest 

Program received signal SIGSEGV, Segmentation fault. 
0x000000050040051c in ??() 
(gdb) bt 
#0 0x000000050040051c in ??() 
#1 0x0000000000000000 in ??() 
(gdb) 

サンプル出力:

  • CentOSの7(64ビット)
  • GCC:gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
  • GDBがgcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)

(別にあります:私は実際の私のコードにバグがありますが、なぜgdbバックトレースが私に詳細な情報を表示しないのか分かりません)。

答えて

5

gdbがプログラムがどこにあるかを知る必要がある情報を含むスタック部分を破壊しました。

0x000000050040051c in ??() 
    ^^^^^^^^ 

これは、コード番号5の4バイト整数です。

main()を開始すると、戻りアドレスがスタックに格納されます。戻りアドレス は、main()が終了したときに戻ってくる場所です。その場所は、main()と呼ばれるランタイムの一部である関数です。

リターンアドレスはコードによってマング/上書きされるため、実行はクラッシュの原因となる存在しないアドレスにジャンプしようとします。

このアドレス0x000000050040051cはプログラムカウンターレジスタになり、SIGSEGV信号がプロセスに渡されるときに格納されます。 gdbはこの情報を検査し、アドレス0x000000050040051cに一致するコードがどこにあるかを調べようとします。存在しません。

+0

すばやく理解できる回答ありがとうございます。私はsegfault()をこれに変更しようとしました: 'void segfault(){raise(SIGSEGV); } 'そしてgdbをもう一度実行しました。スタックトレースを正常に見ることができました。 –

関連する問題