D での開発に関する最近のはなしのメモ
モノが出てくるのはどうせ先になりそうだし、そもそも私はモノを作るよりその周りを作る方が楽しいような人間でモノなんで本当に出てくるかもあやしい。ゆえに思ったことは思った時に書いた方がいい。しかしまぁいつにもましてニッチの狭げなはなし。
GDC
GDC で作った MacOSX版 AREA2048 は時々カクカクすると言われてました。 GDC がランタイムとして使う BoehmGC がどうも回収に入ると 1フレームをはるかに越える時間を使用するみたいです。 PARSEC47 と TUMIKI Fighters は動的確保を全くしないので問題が出ないです。 AREA2048 は少しだけやるので問題が表面化しました。私が今作ってるものは動的確保だらけなのでおはなしになりません。ですがまぁ、今後これを意識する必要はきっと無いと思っています。ありがたいことに BoehmGCを置き替えるつもりらしい からです。昔の Javaの GC に慣らされた id:ABA さんは素晴らしいコードを書いていたため気付かなかったという話。
GDC は delegate の扱いにバグを持っています。これはほとんど確信してますが、再現する小さいコードがなかなか書けません。
逆に言うと、それ以外は DMD の最近の機能は現状それなりに使ってるつもりのコードが MacOSX でも動いてますので、 GDC は相変わらず素晴しいと思いますです。
cygwin の gcc-gdc を入れれば Windows でも gdb でデバッグできるかもね… GDC-0.8 は mingw をサポートしてますので、 gcc-mingw-gdc もそろそろ入るんじゃないかと期待してますです。
glbf
それなりに使いものになるっぽいです。
Io
Io は結局捨てちゃってます。や、きちんと動くんですけど、肝心の Concurrency が D からうまく制御できてないのと PCL で十分だということで。
stacktrace
beroさんに教えていただいたことをやっと理解しはじめました…なるほど… obj の段階で demangle することはできますね…ていうかあの時きちんと man 読んだつもりだったんだけど寝てたんだろうか… (http://d.hatena.ne.jp/shinichiro_h/comment?date=20040710#c)
結論としては、例外が飛んだ場所の正確な行情報が得られる気がする。
> ar x libphobos.a # object 取り出し > objcopy --redefine-sym _d_throw@4=_d_throw_old@4 \ --rename-section .gnu.linkonce.t_d_throw=.gnu.linkonce.t_d_throw_old \ deh2.o # _d_throw を捨てる > cat d_throw.d # 新しい _d_throw だよ extern (Windows) { void _d_throw_old(Object* o); void _d_throw(Object* o) { printf("error\n"); _d_throw_old(o); } } > dmd -c d_throw.d # コンパイル > ar crus libphobos.a *.o # 新しいのを使って phobos 作り直し > cat test_error.d # 実験のためのもの int main() { throw new Error(`hoge`); return 0; } > dmd -c test_error.d # コンパイルして実行します > gcc -o test_error test_error.o libphobos.a -lpthread -lm > ./test_error error Error: hoge
と、 _d_throw を奪うことができた。もう少し凝ったことをやってみる。 d_throw.d をこんな感じに。
import std.c.stdio; extern (C) FILE* popen(char* com, char* type); extern (C) int pclose(FILE* fp); extern (Windows) { void _d_throw_old(Object* o); void _d_throw(Object* o) { int* raddrp; asm { mov raddrp, EBP ; } printf("errored\n"); printf("ebp is %x\n", raddrp); int raddr = *(raddrp+1)-5; printf("address is %x\n", raddr); FILE* fp = popen(`addr2line -e test_error`, `w`); fprintf(fp, "%x\n", raddr); pclose(fp); _d_throw_old(o); } }
呼び出し元アドレスをひっこ抜いてきて、それを addr2line に渡してるだけ。実行。
> ./test_error errored ebp is bfffed54 address is 804a2c8 /home/i/phobos/test_error.d:4 Error: hoge
なんか行情報がずれてるのは DMD の出す行情報がもともとずれてるせい、たぶん。 GDC でやってみると、
> ./test_error errored ebp is bfffecf8 address is 80493b1 /home/i/phobos/gdc/test_error.d:2 zsh: abort ./test_error
落ちられても困るけど行情報はあってるね。落ちてる理由は d_throw.d をめんどいから DMD でコンパイルしてるからじゃないかな。たぶんマジメに C で書けば問題ない気が。
追記: ちなみに Linux なのに extern(Windows) が必要になる DMD版 libphobos.a はどうなのかという感もあります。 GDC のなら extern(C) にすれば OK。
もいっこ追記: d_throw を C で書き直した。でも落ちるのは相変わらずでした。まあ別にいいか。
#includevoid _d_throw_old(void* o); void _d_throw(void* o) { int* raddrp; asm("mov %%ebp, %0" : "=g" (raddrp)); printf("errored\n"); printf("ebp is %x\n", raddrp); int raddr = *(raddrp+1)-5; printf("address is %x\n", raddr); FILE* fp = popen("addr2line -e test_error", "w"); fprintf(fp, "%x\n", raddr); pclose(fp); _d_throw_old(o); }
opCmp
メモ: opCmp の引数は Object にしておいてキャストしないと sort できないので要注意。 covariant な引数が取れないから。