アイエエー 例外? なんで例外?
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; }
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; }
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