« 2008年03月 | メイン | 2008年11月 »

2008年10月 アーカイブ

2008年10月10日

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

2008年10月22日

PageBute

古巣で半分手伝ったプロダクトが紹介されていたので記憶をたぐってみると、
元々はセキュリティ上の問題などでPHPが使えないサーバがあったのと、
丁度そのころMTのリビルド周りを読んでいてページのリビルド終了後の
フックポイントをみつけたので「だいたいこんなもんで出来るんでね?」と言って作ってもらったんでした。
なんで名前がPageButeになったのかはなんでだったでしょう…。

で、仕組みは簡単でリビルド時に

<MTPageContents>
[[何か]]
<$MTPageSeparator$>
</MTPageContents>

というタグが
<!--start-->
[[何か]]
<!--separator-->
[[何か]]
<!--separator-->
[[何か]]
<!--separator-->
<!--end-->

という感じに置き換わり、ページ1枚分のHTMLができたら
<!--start-->〜<!--end-->の中身をセパレータで分けた内容で置き換えてページを作ってファイルに書き出す、
というようなかんじでした、と思いましたが最早記憶が定かではありません。

そんなわけでループ単位の最後に<$MTPageSeparator$>を
入れないとうまく動かなかった気がします。