gcc-sjljでビルドしたバイナリのデバッグ
Mingw gccでは、DWARF-2(DW2)版とSJLJ版というものがあるらしい。検索したところ、それぞれの特徴は以下のようである。
[前略]それまでのMINGWでのC++例外はSjLj (Setjump/Longjump) 例外ハンドリングといって setjump/longjump を使って例外を実装している物で、try...catchがあるたび、あるいはスタック上にインスタンスをおいただけでもそこにsetjumpをするため、例外が発生もしないのに実行コストがかかる物でした。DWARF2はもともとデバッグ情報形式の一つですが、これを用いて例外のcatch先を探すのが DWARF2 Exception Handling (DW2 EH) ということになります。この方式は例外が発生しないかぎりは実行コストがかからないそうです。
TDM's GCC/mingw32 Builds (非公式Mingw gcc配布サイトの解説より):
As a general rule, you should choose the default SJLJ packages, unless you know you need faster exception handling and can guarantee you'll never need to unwind through non-DW2-compiled stack frames (such as a Windows callback).
DW2 unwinding is desirable for a number of reasons, but cannot yet (on Windows) pass exceptions through "foreign" stack frames (code compiled by another non-DW2-enabled compiler, such as OS DLLs in a Windows callback).
簡単に言えば、DW2の方が速いが、他者が開発したものとリンクさせる場合の扱いが難しい、ということのようだ。
蛇足になるが、"unwind"という単語を当初知らず、辞書で引いたが意味がさっぱり通じなかった。(例外発生時の)スタック巻き戻しをこう呼ぶらしく、スタックアンワインドという用語も一般的なようだ。Wikipediaの記事が参考になる。
本題に入る。MSYSでgccのver.4.xを使用しようとした場合、公式のsourceforgeサイトでは、現在、testing版としてgcc-4.3.0-alphaが、テクノロジプレビュー版としてgcc-4.2.1のソースとgcc-4.2.1-sjljが提供されている。
従って、公式ビルドであり、alpha版を避け、なおかつ容易に導入できるという条件をつけると、gcc-4.2.1-sjljのみが候補となる。
そのような理由でgcc-sjljを使い始めたが、gdbを用いたデバッグ時、設定したブレークポイントで正しく停止しないなどの不都合が見つかった。
解決方法は、ビルド時、-gや-ggdbオプションではなく、-gstabsあるいは-gstabs+オプションを用いることだった。
また、ffmpegのビルドオプションでは、--enable-debugで指定した文字列が-gオプションの後の文字列としてビルドされるので、例えば--enable-debug=stabs+とすることでgccに-gstabs+オプションが渡る。
参考:
- Manpage of GCC : gccのオプションについて
- [Mingw-users] gdb 6.6 cannot step over functions in program compiled by gcc 4.2.1-sjlj (mingw32-2)
- [FFmpeg-user] -enable-debug={level} : ffmpegのデバッグオプションについて
最近のコメント