« Pythonでモジュールを動的生成する | メイン | PageBute »

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) #(第一引数)
 (gdb) po *(int*)($ebp+24) #(第ニ引数)
です。以下の引数も8バイトオフセットで取得できます。これはintel macの場合ですが、PPCの場合はr5レジスタに第一引数があるそうです。

参考:

http://www.borkware.com/quickies/one?topic=gdb

トラックバック

このエントリーのトラックバックURL:
http://antas.jp/mtsys/mt-tb.cgi/523

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)