...ing logging 4.0

はてなブログに移行しました。D言語の話とかいろいろ。

Comet2 Simulator 完成

しばらくちまちまと Comet2 Simulator を作っていたが,ようやく完成した.

最後のトラブル

http://d.hatena.ne.jp/haru-s/20080905/1220614420
この間のメモリ破壊のバグは配列の-1番の要素に書き込みをする場合があったからだった.
すべての配列アクセスの前に;

assert(0 <= index && index < ARRAY_SIZE);

を追加してみたら見つかった.
これを直してターゲットマシンで実行してみると,なぜか実行直後に落ちてしまった.
実はネットワークフォルダ上で実行していて,起動時にセキュリティの制限に引っかかって落ちてしまったらしい.
ローカルに置いて実行したらちゃんと動いた.
これにて作業完了.
完成に至るまでここのコメントで助けていただきありがとうございました.

事の発端

http://d.hatena.ne.jp/haru-s/20080702/1215004554
元々のアプリケーションはbetter CとしてのC++で書かれていて,Amuletという古いGUI toolkitが使われていた.
Amuletは今でもオープンソース化したものが残っているようだが,仕様変更によって手元のソースがコンパイルできなくなってしまったらしい.
それにAmuletはWindowsネイティブのlook and feelを持たないらしいこともあって(よく知らないけれど),GUI部分を書き直したいということだった.

紆余曲折

何の言語を使ってもよいとのことだったので,一瞬D言語(GUIライブラリはDFLかな)を使おうかとも考えたが,今回は人様にバイナリとソースを渡すので流石にやめたw
そこでC++/CLIでシミュレータのcoreをラップして.NETライブラリ化してからC#GUIを書き,一応の完成を見たはずだった.
ところが,ターゲットマシンには何も追加インストールしたくないということになった.
ターゲットマシンには.NET2.0は入っているものの,C++ランタイムライブラリは入っていないし,アセンブリ(DLL)を実行ファイルと同じ場所に置いただけではSide by Sideの仕組みによってバインドされない.
http://d.hatena.ne.jp/haru-s/20080831/1220175729
http://d.hatena.ne.jp/haru-s/20080831/1220199143
コメント欄で教えてもらった方法を採ることにした.
シミュレータのcoreはC++ランタイムライブラリを静的リンクしたネイティブのDLLにして,C#でそのDLLのP/Invokeラッパーを書いた.
その後のトラブルは最初に書いたとおり.

感想

それにしても,ものすごく実行効率を気にしたC/C++コードだった.
構造体/クラスのオブジェクトのコピーが一度も発生しないんだもの.
そのせいもあって,グローバル変数を介したやりとりが多かったけど,規模が小さかったのでこれは特に問題にならなかった.
それよりも,コンストラクタが全く実行されるようになっていなくて「RAIIってなにそれ」.
char*が随所で現れまくるのが不安で何度もstd::stringに書き換えたいと思った.
const修飾されていないchar*だからなおさらだ.


そこで,既に書かれているコードが実行効率に注力して書かれている場合に,その実行効率を犠牲にしてまで読みやすさを向上させるのは許されるべきか許されざるべきかで悩んだ.
結果的には,できるだけ効率は落とさないようにしよう,元のコードの変更は最小限にしようと思って,文字列処理のstd::string化と,グローバル変数をやめて戻り値中心のスタイルに書き換えるのは,やめた.


そういうコードをいじってみて思ったのは,type systemに頼ったプログラミングというのはやっぱり安全で安心だし,自分はそっちの方がいいな,ということかな.

それと

メモリの解放を自分でやるのは非現実的だということ.
RAII万歳!std::shared_ptr万歳!