core ファイルを解析するメモ。
下準備
まず意図的に SEGV させるコードを書く。
$ vi a.cpp
#include <stdio.h> 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






