delegateとかアンマネージとかあまり関係有りませんでした、すみません。Releaseモードだとオブジェクトの生存期間が変わってしまうのが原因でした。基本的には以下のページと同様の現象です。
http://blogs.wankuma.com/shuujin/archive/2007/05/15/76794.aspx
コード例を出すときにばっさり省いた箇所が原因でした。具体的にはCvMemStorage。
CvSeqをつくるには、配列データの格納先であるCvMemStorageが必要です。大抵深く考えずその場で作って渡してしまいますが、これが落とし穴。つまりこんなコードだったということです(delegate周りは大幅に省略)。
class Program { CvSeq<int> seq; Program() { CvMemStorage storage = new CvMemStorage(); seq = new CvSeq<int>(SeqType.EltypeS32C1, CvSeq.SizeOf, storage); for(int i=0; i<10000; i++) { Hoge(); } } void Hoge() { seq.Push(0); GC.Collect(); } static void Main(string[] args) { new Program(); } }
この様に、CvSeqだけフィールド変数にして安心していたら、そもそもの配列データが入っているCvMemStorageの方はGCで回収されてしまって、そのあとCvSeqを使おうとすると死亡、という流れのようです。
(ただしこの例のコードでは落ちないかもしれません。どうもうまく別のコードでは再現できない)
これの解決にはCvMemStorageもフィールドで定義するのが一番簡単ですが、なんだか今後もしょっちゅうはまりそうなので、CvSeqに渡されたCvMemStorageをCvSeq内部で保持しておくことにしました。これで上記のコードでも落ちなくなった、はず・・・
.NETのクラスライブラリ設計 開発チーム直伝の設計原則、コーディング標準、パターン (Microsoft.net Development Series)
- 作者: Krzysztof Cwalina,Bard Abrams,藤原雄介
- 出版社/メーカー: 日経BPソフトプレス
- 発売日: 2009/12/24
- メディア: 大型本
- 購入: 10人 クリック: 603回
- この商品を含むブログ (33件) を見る