アイエエー 例外? なんで例外?

C++で未キャッチ例外が発生したときに、スタックトレース(バックトレース)を作成するライブラリです。
https://github.com/rti7743/naichichi2/blob/master/naichichi2/haikuwoyome.h

特徴

ヘッダ単体で使えます。
windows MSVC と Linux gccで動きます。
C++11が使えると、例外の中身も表示されます。
NYSLなので自由に使えます。コピペしてOK。
名前がとてもかっこいい。

遊び方

#include "haikuwoyome.h"

int main()
{
	//これ以降で、未キャッチ例外が発生したら、スタックトレースを生成します.
	HaikuWoYome::KaisyakuShiteYaru(); //ハイクを詠め。介錯してやる。

	f();
	
	return 0;
}
#include "haikuwoyome.h"

void ff()
{
	*(int*)0 = 0;
}


void f()
{
	ff();
}

int main()
{
	//これ以降で、未キャッチ例外が発生したら、スタックトレースを生成します.
	HaikuWoYome::KaisyakuShiteYaru(); //ハイクを詠め。介錯してやる。

	f();

	return 0;
}

コンパイル C++11 が使える場合

g++  -std=c++11  -Wl,--no-as-needed -ldl  a.cpp


出力例

=HAIKU=============================================
backtrace:
HaikuWoYome::BackTrace() ./a.out() [0x402798]
HaikuWoYome::OnSignalFunction(int) ./a.out() [0x402c08]
/lib/x86_64-linux-gnu/libc.so.6(+0x354b0) [0x7fc5dbe484b0]
ff() ./a.out() [0x402ed0]
f() ./a.out() [0x402ee2]
main ./a.out() [0x402ef3]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7fc5dbe33830]
_start ./a.out() [0x401849]

signal: 11 (SIGSEGV)
process_id: 29259 thread_id:29259
===================================================

C++11がない場合でも、同一です。

g++   -Wl,--no-as-needed -ldl  a.cpp
=HAIKU=============================================
backtrace:
HaikuWoYome::BackTrace() ./a.out() [0x40204e]
HaikuWoYome::OnSignalFunction(int) ./a.out() [0x4024be]
/lib/x86_64-linux-gnu/libc.so.6(+0x354b0) [0x7f766a3d84b0]
ff() ./a.out() [0x402786]
f() ./a.out() [0x402798]
main ./a.out() [0x4027a9]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f766a3c3830]
_start ./a.out() [0x4014c9]

signal: 11 (SIGSEGV)
process_id: 29277 thread_id:29277
===================================================
#include "haikuwoyome.h"

void ff()
{
	throw std::runtime_error("さよならー");
}


void f()
{
	ff();
}

int main()
{
	//これ以降で、未キャッチ例外が発生したら、スタックトレースを生成します.
	HaikuWoYome::KaisyakuShiteYaru(); //ハイクを詠め。介錯してやる。

	f();

	return 0;
}

コンパイル C++11 が使える場合

g++  -std=c++11  -Wl,--no-as-needed -ldl  a.cpp


出力例

=HAIKU=============================================
backtrace:
__cxa_throw ./a.out(__cxa_throw+0x47) [0x402a28]
ff() ./a.out() [0x40306a]
f() ./a.out() [0x403089]
main ./a.out() [0x40309a]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f4b4ac47830]
_start ./a.out() [0x4019b9]

exception: std::runtime_error さよならー
process_id: 29693 thread_id:29693
===================================================


C++11がない場合は、例外の中身を取得できません.

g++   -Wl,--no-as-needed -ldl  a.cpp
=HAIKU=============================================
backtrace:
__cxa_throw ./a.out(__cxa_throw+0x47) [0x40235e]
ff() ./a.out() [0x4029ee]
f() ./a.out() [0x402a2a]
main ./a.out() [0x402a3b]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7fca4fb5c830]
_start ./a.out() [0x4016b9]

process_id: 29685 thread_id:29685
===================================================

標準は stderrに出力するだけですが、カスタムすこともできます。

#include <stdio.h>

//私のロガーです
void mylogger(const char* msg)
{
        puts("HELLO");
        puts(msg);
        puts("/HELLO");
}

//私のロガーを使います.
#define HAIKU_WO_YOME_OUTPUT_STDERR(MSG) mylogger(MSG)
#include "haikuwoyome.h"



void ff()
{
        throw std::runtime_error("さよならー");
}

void f()
{
        ff();
}

int main()
{
        //これ以降で、未キャッチ例外が発生したら、スタックトレースを生成します.
        HaikuWoYome::KaisyakuShiteYaru(); //ハイクを詠め。介錯してやる。

        f();

        return 0;
}
HELLO
=HAIKU=============================================
backtrace:
__cxa_throw ./a.out(__cxa_throw+0x47) [0x402a17]
ff() ./a.out() [0x403045]
f() ./a.out() [0x403064]
main ./a.out() [0x403075]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7ff44e551830]
_start ./a.out() [0x401979]

exception: std::runtime_error さよならー
process_id: 28341 thread_id:28341
===================================================

/HELLO


std::exceptionを基底にもたない例外を使いたい場合は、以下のようにします。

#include <stdio.h>
#include <string>

class MyException
{
        std::string msg;
public:
        MyException() {}
        MyException(const std::string& msg) { this->msg = msg; }
        virtual ~MyException(){}

        std::string what() const{ return this->msg; }
        //
        //または、
        //const char* what() const{ return this->msg.c_str() ; }
};

//私のロガーです
void mylogger(const char* msg)
{
        puts(msg);
}

//私のロガーを使います.
#define HAIKU_WO_YOME_OUTPUT_STDERR(MSG) mylogger(MSG)
//私の作った例外を使います.
#define HAIKU_WO_YOME_YOUR_EXECPTION_CLASS MyException
#include "haikuwoyome.h"

void ff()
{
        throw MyException("さよならー");
}


void f()
{
        ff();
}

int main()
{
        //これ以降で、未キャッチ例外が発生したら、スタックトレースを生成します.
        HaikuWoYome::KaisyakuShiteYaru(); //ハイクを詠め。介錯してやる。

        f();

        return 0;
}
=HAIKU=============================================
backtrace:
__cxa_throw ./a.out(__cxa_throw+0x47) [0x402a7f]
ff() ./a.out() [0x4030fb]
f() ./a.out() [0x403137]
main ./a.out() [0x403148]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f5ca9c6e830]
_start ./a.out() [0x401999]

exception: MyException さよならー
process_id: 28812 thread_id:28812
===================================================

当然ですが、例外をキャッチすると何も表示されません。

#include "haikuwoyome.h"

void ff()
{
	throw std::runtime_error("うぼあー");
}


void f()
{
	ff();
}

int main()
{
	//これ以降で、未キャッチ例外が発生したら、スタックトレースを生成します.
	HaikuWoYome::KaisyakuShiteYaru(); //ハイクを詠め。介錯してやる。

	try
	{
		f();
	}
	catch(std::exception& e)
	{
	}
	return 0;
}

出力例…当然何もでない.


この例外を投げたのは誰だー

この例外を投げたのは誰だーから6年。やっと解決したっぽい。

この例外を投げたのは誰だー
http://d.hatena.ne.jp/rti7743/20110109/1294605380