0

Segmentation Fault Core Dumpから被疑箇所特定

Capture 2017-02-18 16.54.16

2016年度も多くの方にご訪問いただき、誠にありがとうございました。

Linuxのプログラムをデバッグするとき、一番やっかいな、かの「Segmentation Fault」について。
先日、知り合いに対応を頼まれたので、そのエッセンスを。。

ただ、プログラムが膨大でマルチプロセス等を使っていたら、どこで問題を起こしているのかすらわからないです。
今回はLinuxのCore Dump機能で問題発生行を特定する方法を紹介します。

まず、前提としてはSegmentation Faultは再現できること。(当たり前ですが・・・)

下記のプログラムを例とします。

#include
#include

#define DATA "TEST"

char mngfile[2][50];

int main()
{
  memset( mngfile, '\0', sizeof(mngfile) );

  GetMngFile(mngfile);

  return 0;
}

int GetMngFile( mngfile )
  char mngfile[2][50];
{
  int i=0;
  char    file[128];
  for(i=0;i<999;i++)
  {
    memset( file, '\0', sizeof(file) );

    strcpy(file,"abc");
    sprintf(mngfile[i],"%s_%s",file,DATA);
    printf("%d,%s\n",i,mngfile[i]);
  }
  return 0;
}

次に、コンパイルオプションに「-g」を付けてコンパイルします。

gcc test2.c -g -o test2

多くのLinuxではデフォルトCoreDump機能を無効にしてあるため、有効にします。

ulimit -c unlimited (生成するCoreのサイズを制限しない)

プログラムを実行してみます。

./test2
セグメンテーション違反です (core dumped)

この時、カレントディレクトリで「core.11504」のようなファイルが生成されます。

このCoreをGDBでデバッグしてみましょう。

gdb ./test2 core.11504
・
・
・
Core was generated by `./test2'. 
(test2がCoreを吐いている)
Program terminated with signal 11, Segmentation fault.
(シグナル11でプログラムが終了され、セグメンテーション違反発生)
Reading symbols from /lib/tls/libc.so.6...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0  0x0058668b in _IO_default_xsputn_internal () from /lib/tls/libc.so.6 
(最終実行ステップはlibc.so.6ライブラリの_IO_default_xsputn_internal()関数内にある)
(gdb)bt  (BackTraceしてみます。)
#0  0x0058668b in _IO_default_xsputn_internal () from /lib/tls/libc.so.6
#1  0x005645fa in vfprintf () from /lib/tls/libc.so.6
#2  0x0057c71b in vsprintf () from /lib/tls/libc.so.6
#3  0x0056995b in sprintf () from /lib/tls/libc.so.6
#4  0x080484ce in GetMngFile (mngfile=0x8049740) at test2.c:27
#5  0x08048441 in main () at test2.c:12
わたしのソースにのみ興味があるので、先頭にあるStack Frame番号の詳細をみます。
(gdb) frame 4
#4  0x080484ce in GetMngFile (mngfile=0x8049740) at test2.c:27
sprintf(mngfile[i],"%s_%s",file,DATA);

これで上記ソースの太字箇所 sprintfで問題があることを判明しました。
このソースをよく見ると、配列mngfileの定義数を超えたメモリー領域のデータ改ざんのあったので、
これで問題判明です。

以上です。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です