C/C++でSegmentation faultが発生した場所を特定する方法

C/C++でSegmentation faultが発生した場所を特定する方法

Posted at March 14,2017 12:03 AM
Tag:[C/C++]

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"オプションが必要です。

簡単なサンプルでしか確認していないので、すべてのパターンに適用できるか分かりませんがとりあえず。

関連記事
トラックバックURL


コメントする
greeting

*必須

*必須(非表示)


ご質問のコメントの回答については、内容あるいは多忙の場合、1週間以上かかる場合があります。また、すべてのご質問にはお答えできない可能性があります。予めご了承ください。

太字イタリックアンダーラインハイパーリンク引用
[サインインしない場合はここにCAPTCHAを表示します]

コメント投稿後にScript Errorや500エラーが表示された場合は、すぐに再送信せず、ブラウザの「戻る」ボタンで一旦エントリーのページに戻り(プレビュー画面で投稿した場合は、投稿内容をマウスコピーしてからエントリーのページに戻り)、ブラウザをリロードして投稿コメントが反映されていることを確認してください。

コメント欄に(X)HTMLタグやMTタグを記述される場合、「<」は「&lt;」、「>」は「&gt;」と入力してください。例えば「<$MTBlogURL$>」は「&lt;$MTBlogURL$&gt;」となります(全て半角文字)