2008年の3月にリリースされたgdb-6.8の目玉機能の一つに「C++サポートの強化」があります*1。この機能を使うと、STLやboostのようなテンプレートを使ったコードのデバッグがかなり楽になります。C++使いの方は、是非gdbを6.8にupgradeしましょう。

具体的に、以下のようなコードを使って、「C++サポートの強化」について説明します。

#include <iostream> using namespace std; template < typename T> class A { public : void func() { cout << sizeof (T) << endl; } }; int main() { A< int > integer; A< double > real; integer.func(); real.func(); return 0 ; }

このコードに対して、6.7以前のgdbで func() にブレークポイントを設定します。test.cppの9行目なので以下のようになります

(gdb) break test.cpp: 9 Breakpoint 1 at 0x80486fc : file test.cpp, line 9 .

emacs上で gdb を使ってる場合は

func()の行にカーソルをおいた状態で、c-x SPACE を押す

func()の行の左側をマウスでクリック

のような操作でブレークポイントが設定できます。

ところが従来のgdbではここで問題が生じます。恐ろしいことに、この状態では func() でプログラムがブレークしない場合があるのです。ブレークポイントを設定したのにも関わらずです。

どういうことかというと、それは次のように info breakpoints でブレークポイントの一覧を見るとわかります。

(gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 0x080486fc in A<int>::func() at test.cpp: 9

このように、func()には実体が二つ、つまりA ::func() と A ::func()とがあり、ブレークポイントは A ::func() の方にだけ設定されていたのです。そのため、古いgdbでは A ::func() ではブレークせずに通過してしまいます。このような恐ろしい罠が以前のgdbにはありました。

gdb-6.8の「C++サポートの強化」とは、この問題を解決するものです。具体的には gdb-6.8 では、同じようにブレークポイントを設定するだけで

(gdb) b test.cpp: 9 Breakpoint 1 at 0x80486fc : file test.cpp, line 9 . ( 2 locations)

自動的に、実体のある関数すべてにブレークポイントを設定してくれます。

(gdb) i b Num Type Disp Enb Address What 1 breakpoint keep y <MULTIPLE> 0x080486fc 1 . 1 y 0x080486fc in A<int>::func() at test.cpp: 9 1 . 2 y 0x08048728 in A<double>::func() at test.cpp: 9

この機能のおかげで、何も考えずとも毎回ちゃんとfunc()でブレークしてくれます。実に直感的な挙動です。

ついでに、A ::func()側だけブレークポイントを無効にしたい場合は

(gdb) disable 1 . 2

とします。詳細は本家のマニュアルをどうぞ。

http://sourceware.org/gdb/current/onlinedocs/gdb_6.html#SEC33