gdb + core 解析
core ファイルを解析するメモ。
下準備
まず意図的に SEGV させるコードを書く。
$ vi a.cpp
#include
class CPrint
{
private:
int m_number;
char *m_str;
public:
CPrint() : m_number(10), m_str(NULL) {}
~CPrint() {}
void print(){
// ここで SEGV る予定
printf( "%d, %c\n", m_number, m_str[0] );
}
};
int main()
{
CPrint p;
p.print();
return 0;
}
続けて core を出力させる設定。環境は Linux CentOS 5。
$ ulimit -c unlimited
core dumped
下準備で作成したソースコードをコンパイル。-g を忘れずに。
$ g++ a.cpp -g
実行する。当然 SEGV る。
$ ./a.out
セグメンテーション違反です (core dumped)
core ファイルが吐かれていることを確認。
$ ls
a.cpp a.out core.1613
core 解析
gdb を立ち上げる。gdb 実行バイナリ coreファイル
$ gdb a.out core.1613
...
Program terminated with signal 11, Segmentation fault.
#0 0x08048568 in CPrint::print (this=0xbfe45794) at a.cpp:15
15 printf( "%d, %c\n", m_number, m_str[0] );
(gdb)
呼び出された順番で関数を表示する。
(gdb) where
#0 0x08048568 in CPrint::print (this=0xbfe45794) at a.cpp:15
#1 0x080484fd in main () at a.cpp:22
(gdb)
ソースコードを表示する。
(gdb) list
10 CPrint() : m_number(10), m_str(NULL) {}
11 ~CPrint() {}
12
13 void print(){
14 // ここで SEGV る予定
15 printf( "%d, %c\n", m_number, m_str[0] );
16 }
17 };
18
19 int main()
(gdb)
変数の値を確認する。
クラスのメンバ変数もアドレスさえ分かれば確認できる。
(gdb) p ((class CPrint *) 0xbfe45794)->m_number
$2 = 10
(gdb)
いちいち ((class CPrint *) 0xbfe45794) とうつのが面倒な場合は、変数に代入する。
(gdb) set $c = ((class CPrint *) 0xbfe45794)
(gdb) p $c->m_number
$3 = 10
(gdb) p $c->m_str
$4 = 0x0