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

March 14,2017 12:03 AM
Category:[C/C++]
Tag:[C/C++]
Permalink

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

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

Comments [0] | Trackbacks [0]

IEのタブに色がつく理由

March 9,2017 12:03 AM
Category:[IE]
Tag:[IE, Windows]
Permalink

IEのタブに色がつく理由を調べてみました。

1.はじめに

IEで複数のタブを開くと、下のスクリーンショットのように色がつく場合があります。

複数のタブ

逆に色がつかない場合もありますが、その違いがわかりません。

ということで、IEのタブに色がつく理由を調べてみました。

2.タブに色がつく理由

タブに色がつくのは、あるページから新しいタブを開いたとき、色分けすることでタブのグループをわかりやすくするための仕組みです。

たとえばYahooのページのタブをひとつだけ開いているときは色がつきません。

タブをひとつだけ開いているとき

この状態でページ内の任意のリンクを新しいタブで開くと、タブに色がつきます。

新しいタブ

Yahooとは関係のない別のページを開い、そのページにある任意のリンクを新しいタブで開くと、異なる色がつきます。

新しいタブ

配色の順序はランダムのようです。

3.色分けをやめる

色分けをやめたいときは、「ツール」→「インターネットオプション」をクリック。

インターネットオプション

「全般」タブ→「タブ」をクリック。

タブ

「タブグループを有効にする」のチェックを外して「OK」をクリック。

タブグループを有効にする

IE再起動後、色分けがされなくなります。

再起動後

4.色分けされた状態でタブを移動した場合

色分けされた状態のタブを移動した場合、移動したタブの色は、

  • 移動先の左右のタブの色が同じ場合、その色に変わる
  • 移動先の左右のタブの色が異なる場合、解除

となるようです(個人的にはこの仕様はどうかと思いますが...)。

移動元のタブ色も最後の1つになると色が解除されます。

移動前
移動前

移動後
移動後

Comments [0] | Trackbacks [0]

C++で「invalid abstract type~」というエラーになる場合の対処

March 8,2017 12:03 AM
Category:[C/C++]
Tag:[C/C++]
Permalink

C++で「invalid abstract type~」「because the following virtual functions are pure within~」というエラーになる場合の対処方法について紹介します。

1.問題点

下記のサンプルプログラムを作りました。

sample.h

class Sample {
    public:
        Sample();
        void test1();
        virtual void test2() = 0;
};

sample.cc

#include <stdio.h>
#include "sample.h"
 
Sample::Sample() {
}
 
void Sample::test1() {
    printf("%s\n", "Hello World!");
}
 
void Sample::test2() {
}

test.cc

#include "sample.h"
 
Sample sample[10];
 
int main() {
    sample[0].test1();
    return 0;
}

このプログラムをコンパイルすると、下記の「invalid abstract type~」「because the following virtual functions are pure within~」というエラーに遭遇します。

% g++ test.cc sample.cc
test.cc:3:17: エラー: invalid abstract type 'Sample' for 'sample'
 Sample sample[10];
                 ^
In file included from test.cc:1:0:
sample.h:1:7: 備考:   because the following virtual functions are pure within 'Sample':
 class Sample {
       ^
sample.h:5:22: 備考:    virtual void Sample::test2()
         virtual void test2() = 0;
                      ^

2.原因

純粋仮想関数(pure virtual function)をもつクラスは抽象クラス(abstract class)となるので、その型のオブジェクトは定義できないようです。

3.対処

クラス定義をポインタ型にすることでこのエラーを回避できます。

#include "sample.h"
 
Sample *sample[10];
 
int main() {
    sample[0]->test1();
    return 0;
}

ポインタ型にするため、関数へのアクセスは"."ではなく、"->"に変更します。

4.参考サイト

参考サイトは下記です。ありがとうございました。

Comments [0] | Trackbacks [0]
 1  |  2  |  3  |  4  |  5  | All pages