GDB with Objective-C
そういえば会社ブログがあったことを思い出しました。
最近はMacでの開発を行っていたのですが、
GDBを使った小技についてまとめようと思います。
リモートデバッグの使いどころ
XCodeに付属しているデバッガは使いやすいのですが、同じマシンでデバッグする場合、ブレークポイントでデバッガが起動したときに、デバッグ対象のウィンドウが非アクティブになってしまいます。こういうときはリモートデバッグの出番です。おもむろにデバッグ対象のMacに対して別のマシンからSSHでログインし、$ gdb --pid=<<process id>>でデバッグ対象のプロセスにアタッチしましょう。SSHクライアントを動かすマシンのOSは何でもいいです。
メモリリークしているオブジェクトの参照カウントを調べる
まず調べる対象のオブジェクトを利用している付近で一度ブレークポイントを仕込み、オブジェクトのメモリアドレスを調べ、どこかにメモしておきます。あとは気になるところでgdbをブレークさせて、デバッガコンソールで(gdb) p (int)[メモったメモリアドレス retainCount]で調べてみましょう。すでにメモリが解放されていた場合は何かエラーが返ってきますし、生きていた場合は参照カウントの数が取得できます。
メソッドの呼び出し直後でブレークさせてその引数を調べる
Cocoa内部のAPIの様子をうかがう方法です。まずデバッガーのブレークポイントに+[NSObject alloc]のように、メソッドのシグネチャを追加します。これでデバッグ実行するとメソッドが呼び出された直後にブレークするので、デバッガのコンソールで
-[NSWindowController showWindow:]
(gdb) po *(int*)($ebp+8)とすると、その時のselfが出力されます。$ebpは現在のスタックフレームの底のポインタですので、スタックフレームの底から数えて3つめに入っていることになります。また、引数は
(gdb) po *(int*)($ebp+16) #(第一引数)です。以下の引数も8バイトオフセットで取得できます。これはintel macの場合ですが、PPCの場合はr5レジスタに第一引数があるそうです。
(gdb) po *(int*)($ebp+24) #(第ニ引数)
参考: