あるライブラリを用いたソースで、Releaseビルドではエラーになってしまうというプログラムがあり調査していました。ライブラリ製造元から出してくれているサンプルでは同様の処理を問題なくこなしているのに、プロジェクトメンバーが作ったソースはだめ。何が違うのかを1つずつ見ていったところ……
- ライブラリにある処理をデリゲートしたあと、そのポインタのGCHandleを取得していない。
- 上記のGCHandleをFreeしていない。
- 主処理のTry句の中で、ライブラリのメインオブジェクトをDisposeしてしまっている。
おそらくビルドタイプでエラーが出るというのは3つめのDisposeが原因かと。これを削除するだけでエラーは消えました。私もこのあたりあんまりよく分かりきっていないので推測ですが、まだ使ったり多段的に片付けをしなければならないオブジェクトの外枠をDisposeしてしまったことで、デリゲートして渡されたものなどが宙ぶらりんになってしまうなどの現象が起きたのではないかと。
また、GCHandleを取得していないことで、デリゲートで渡している処理がきちんと走らないという現象が起きてしまっていました。これはもしかして、デリゲートとして渡したあとに.NETが「使ってないなら消すよ」とガベージコレクトしてしまったのではないかと……。GCHandleを取得することで、ガベージコレクタの対象からはずれてうまく動くようになったのかな?
何にせよややこしいし難しいですねこのあたり。きちんと理解しておかないとだめだなぁ。
参考までに調べるに使ったサイトの情報を掲載しておきます。
- リリースビルド作成時によくある問題(MSDN、C、C++ビルドのリファレンス)
- http://msdn.microsoft.com/ja-jp/library/dykf6bx9.aspx
- 誰も参照していないフォームは、何故GCの対象にならないのか(囚人のジレンマな日々)
- http://blogs.wankuma.com/shuujin/archive/2006/02/27/21562.aspx
- VarPtr, StrPtr, ObjPtr関数の代わりになるものは?(dobon.net)
- http://dobon.net/vb/dotnet/vb6/objptr.html