ちょうどアジは西日本の日本海側が本場ということもあって,僕の地元では岸壁に立ってサビキをすると小アジがたくさん釣れました.
さて,google-glogと言えばgoogle謹製のログライブラリ.
Google Japan Blog: C++ のプログラムのデバッグを楽にする方法にて概要が紹介されていて,ドキュメントには簡単なチュートリアルがあります.基本的には使い方に難しいところは何も無いです.
お魚さん的には学部卒論のときから使っててもはや手放せないんですが,作業が切羽詰ってくるとあんまり律儀にログを出す余裕がなくなってきますw
そんな時でもただ一ついつでも使ってたのが,「落ちた時にスタックトレースを吐く機能」です.
ということで今回はそれに絞って紹介.まとまった記事を書くには今時間的余裕がない><
google-glogの導入
Linuxを想定してます.
google-glog – Logging library for C++ – Google Project Hostingから落として,普通にやるだけ.
% wget http://google-glog.googlecode.com/files/glog-0.3.2.tar.gz % tar xf glog-0.3.2.tar.gz % cd glog-0.3.2 % ./configure % make % make check % sudo make install
一般的な話ですがconfigureの引数に”–prefix=hoge”をつけるとインストール先を変えられます.すなわち,hoge/includeやhoge/libにそれぞれ格納される形になります.
使い方
最低限のサンプルです.スニペットとして使ってもらえると思います.
コンパイル時はlibglog.aをリンクします.
% g++ prog.cpp -lglog
結果の例
例に載せたサンプルプログラムはfuncで死ぬのですが,その時にこんなかんじでスタックトレースを吐いてくれます.
terminate called without an active exception *** Aborted at 1357235745 (unix time) try "date -d @1357235745" if you are using GNU date *** PC: @ 0x7f31bffa93e5 (unknown) *** SIGABRT (@0xd3e00007bc0) received by PID 31680 (TID 0x7f31c0ed1740) from PID 31680; stack trace: *** @ 0x7f31bffa9460 (unknown) @ 0x7f31bffa93e5 (unknown) @ 0x7f31bffacb4b (unknown) @ 0x7f31c086bd7d (unknown) @ 0x7f31c0869f26 (unknown) @ 0x7f31c0869f53 (unknown) @ 0x7f31c086a096 (unknown) @ 0x400775 func() @ 0x40079d main @ 0x7f31bff9430d (unknown) @ 0x400689 zsh: abort ./a.out
最適化による出力内容の違い
ここからはわりと興味.
気になったので見てみた.
結論から言うと,スタックトレースがちゃんと意味のあるかんじになるためには,最適化なしのデバッグシンボル付き(“-O0 -g”)にしておくとよいです.
“-O3″オプション
シンボル消えちゃうからでしょうね,何かの無限ループに陥って止まってるようです.
O2およびOsでも結果は一緒でした.
terminate called without an active exception *** Aborted at 1357236054 (unix time) try "date -d @1357236054" if you are using GNU date *** PC: @ 0x7f9e56cb43e5 (unknown) *** SIGABRT (@0xd3e00007bfc) received by PID 31740 (TID 0x7f9e57bdc740) from PID 31740; stack trace: *** @ 0x7f9e56cb4460 (unknown) @ 0x7f9e56cb43e5 (unknown) @ 0x7f9e56cb7b4b (unknown) @ 0x7f9e57576d7d (unknown) @ 0x7f9e57574f26 (unknown) @ 0x7f9e57574f53 (unknown) @ 0x7f9e57575096 (unknown) ^C
“-O3 -g”オプション
- gオプションはデバッグシンボルを有効にするオプションで,gdbなんかでデバッグするのに必要になります.
これでもやっぱりO3効果で関数名が落とされてて名前が見えません.
O3はあまりしないほうがいいと言うしなぁ.
こっちもO2やOsと結果は一緒でした.
terminate called without an active exception *** Aborted at 1357236131 (unix time) try "date -d @1357236131" if you are using GNU date *** PC: @ 0x7f28307fa3e5 (unknown) *** SIGABRT (@0xd3e00007c14) received by PID 31764 (TID 0x7f2831722740) from PID 31764; stack trace: *** @ 0x7f28307fa460 (unknown) @ 0x7f28307fa3e5 (unknown) @ 0x7f28307fdb4b (unknown) @ 0x7f28310bcd7d (unknown) @ 0x7f28310baf26 (unknown) @ 0x7f28310baf53 (unknown) @ 0x7f28310bb096 (unknown) @ 0x400676 main @ 0x7f28307e530d (unknown) @ 0x4006a1 zsh: abort ./a.out
“-O1″オプションと”-O1 -g”オプション
省略しますがO2やO3のときのと-O0のときのちょうど中間みたいな結果になりました.
一応スタックトレースとしてはちゃんと出ました.
“-O0 -g”オプション
デバッグするときの一般的なモードですね.
なのでシンボルもしっかり残っててくれます.
terminate called without an active exception *** Aborted at 1357236257 (unix time) try "date -d @1357236257" if you are using GNU date *** PC: @ 0x7f9c9e95a3e5 (unknown) *** SIGABRT (@0xd3e00007c35) received by PID 31797 (TID 0x7f9c9f882740) from PID 31797; stack trace: *** @ 0x7f9c9e95a460 (unknown) @ 0x7f9c9e95a3e5 (unknown) @ 0x7f9c9e95db4b (unknown) @ 0x7f9c9f21cd7d (unknown) @ 0x7f9c9f21af26 (unknown) @ 0x7f9c9f21af53 (unknown) @ 0x7f9c9f21b096 (unknown) @ 0x400775 func() @ 0x40079d main @ 0x7f9c9e94530d (unknown) @ 0x400689 zsh: abort ./a.out
まとめ
ということで,特に研究プログラムとかだと,とりあえずコード書き始めたらまずはスタックトレース吐くスニペット貼って,そこからコード書くと,落ちてから原因追求のためにあれこれするコストが無視できないレベルで減ると思います.
ぜひ活用してください.
1年以上前から使ってるのにこのタイミングで書いたのはオブラートに包んで言うと現実逃避です.(←