C/C++でSegmentation faultが発生した場所を特定する方法
C/C++でSegmentation faultが発生した場所を特定する方法を紹介します。
1.問題点
下記のサンプルプログラム(test.cc)を作りました。
test.cc
#include <stdio.h>
void test() {
char *p;
p = 0;
printf("%c\n", *p);
}
int main() {
test();
return 1;
}
コンパイルします。
% g++ -g test.cc
このプログラムを実行するとSegmentation faultが発生します。
% ./a.out
Segmentation fault (コアダンプ)
が、どこでエラーが発生しているのかわかりません。
ということで、C/C++でSegmentation faultが発生した場所を特定する方法を紹介します。
使用しているLinuxはCentOSです。
本来解としてコアダンプを解析する方法もありますが、そちらについては別途エントリーします。
2.Segmentation faultが発生した場所を特定する
Segmentation faultが発生した場所を特定するには、下記の環境変数を設定します。
% export LD_PRELOAD="/lib64/libSegFault.so"
% export SEGFAULT_SIGNALS="all"
上記は64bit版で、32bit版の場合は下記です。
% export LD_PRELOAD="/lib/libSegFault.so"
% export SEGFAULT_SIGNALS="all"
これでサンプルを実行すると、エラーの詳細が出力されます。
% ./a.out
*** Segmentation fault
Register dump:
RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000400570
RDX: 00007ffeeac84158 RSI: 00007ffeeac84148 RDI: 0000000000000001
RBP: 00007ffeeac84050 R8 : 00007f197757ae80 R9 : 0000000000000000
R10: 00007ffeeac83eb0 R11: 00007f19771e0a20 R12: 0000000000400440
R13: 00007ffeeac84140 R14: 0000000000000000 R15: 0000000000000000
RSP: 00007ffeeac84040
RIP: 0000000000400544 EFLAGS: 00010202
CS: 0033 FS: 0000 GS: 0000
Trap: 0000000e Error: 00000004 OldMask: 00000000 CR2: 00000000
FPUCW: 0000037f FPUSW: 00000000 TAG: 00000000
RIP: 00000000 RDP: 00000000
ST(0) 0000 0000000000000000 ST(1) 0000 0000000000000000
ST(2) 0000 0000000000000000 ST(3) 0000 0000000000000000
ST(4) 0000 0000000000000000 ST(5) 0000 0000000000000000
ST(6) 0000 0000000000000000 ST(7) 0000 0000000000000000
mxcsr: 1f80
XMM0: 00000000000000000000000000000000 XMM1: 00000000000000000000000000000000
XMM2: 00000000000000000000000000000000 XMM3: 00000000000000000000000000000000
XMM4: 00000000000000000000000000000000 XMM5: 00000000000000000000000000000000
XMM6: 00000000000000000000000000000000 XMM7: 00000000000000000000000000000000
XMM8: 00000000000000000000000000000000 XMM9: 00000000000000000000000000000000
XMM10: 00000000000000000000000000000000 XMM11: 00000000000000000000000000000000
XMM12: 00000000000000000000000000000000 XMM13: 00000000000000000000000000000000
XMM14: 00000000000000000000000000000000 XMM15: 00000000000000000000000000000000
Backtrace:
./a.out[0x400544]
./a.out[0x400566]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f19771e0b15]
./a.out[0x400469]
Memory map:
00400000-00401000 r-xp 00000000 fd:02 139776506 /home/foo/a.out
00600000-00601000 r--p 00000000 fd:02 139776506 /home/foo/a.out
00601000-00602000 rw-p 00001000 fd:02 139776506 /home/foo/a.out
00894000-008b5000 rw-p 00000000 00:00 0 [heap]
7f1976fa9000-7f1976fbe000 r-xp 00000000 fd:00 201326729 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f1976fbe000-7f19771bd000 ---p 00015000 fd:00 201326729 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f19771bd000-7f19771be000 r--p 00014000 fd:00 201326729 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f19771be000-7f19771bf000 rw-p 00015000 fd:00 201326729 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f19771bf000-7f1977375000 r-xp 00000000 fd:00 201329562 /usr/lib64/libc-2.17.so
7f1977375000-7f1977575000 ---p 001b6000 fd:00 201329562 /usr/lib64/libc-2.17.so
7f1977575000-7f1977579000 r--p 001b6000 fd:00 201329562 /usr/lib64/libc-2.17.so
7f1977579000-7f197757b000 rw-p 001ba000 fd:00 201329562 /usr/lib64/libc-2.17.so
7f197757b000-7f1977580000 rw-p 00000000 00:00 0
7f1977580000-7f1977584000 r-xp 00000000 fd:00 201329559 /usr/lib64/libSegFault.so
7f1977584000-7f1977783000 ---p 00004000 fd:00 201329559 /usr/lib64/libSegFault.so
7f1977783000-7f1977784000 r--p 00003000 fd:00 201329559 /usr/lib64/libSegFault.so
7f1977784000-7f1977785000 rw-p 00004000 fd:00 201329559 /usr/lib64/libSegFault.so
7f1977785000-7f19777a6000 r-xp 00000000 fd:00 201329555 /usr/lib64/ld-2.17.so
7f197798e000-7f1977991000 rw-p 00000000 00:00 0
7f19779a5000-7f19779a6000 rw-p 00000000 00:00 0
7f19779a6000-7f19779a7000 r--p 00021000 fd:00 201329555 /usr/lib64/ld-2.17.so
7f19779a7000-7f19779a8000 rw-p 00022000 fd:00 201329555 /usr/lib64/ld-2.17.so
7f19779a8000-7f19779a9000 rw-p 00000000 00:00 0
7ffeeac64000-7ffeeac85000 rw-p 00000000 00:00 0 [stack]
7ffeeacdd000-7ffeeacdf000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Segmentation fault (コアダンプ)
最後に、「Backtrace:」の最初に表示されたアドレスをaddr2lineコマンドで変換すると、エラーになったファイルと行番号が表示されます。
% addr2line -e a.out 0x400544
/home/foo/test.cc:6
なお、この情報を出力するには、g++でビルドする際に"-g"オプションが必要です。
簡単なサンプルでしか確認していないので、すべてのパターンに適用できるか分かりませんがとりあえず。
Posted by yujiro このページの先頭に戻る
トラックバックURL
コメントする
greeting