ラッパー用ファクトリ関数でdeleteすると落ちる
以下のように、C++のクラスのインスタンスを作成するため、C#からDllImportで呼び出せるようなファクトリ関数を作ってあるとします。
#define EXTERN(type) extern "C" __declspec(dllexport) type __cdecl EXTERN(std::vector<int>*) vector_new() { return new std::vector<int>; } EXTERN(void) vector_delete(std::vector<int>* vec) { delete vec; } // vectorに結果を入れてくれる何かの関数 EXTERN(void) hoge(std::vector<int>* vec) { vec->clear(); vec->resize(100); ..... }
これをC#から呼び出すと、自分の環境では vector_delete のところでダイアログが出てプログラムが落ちます。
[DllImport("mylib.dll")] extern static IntPtr vector_new(); [DllImport("mylib.dll")] extern static void vector_delete(IntPtr vec); [DllImport("mylib.dll")] extern static int hoge(IntPtr vec); static void Main(string[] args) { IntPtr vec = vector_new(); hoge(vec); vector_delete(vec); }
どんなクラスでも落ちるわけではないようで、試したところでは、内部でメモリを動的に確保していなさそうなクラスでは通常通りdeleteができました。
vectorに適当な処理を行う関数 hoge ですが、これを自分で作るとまったく問題なくdeleteできます。しかしこれが他のライブラリ、具体的にはOpenCVにある関数だった場合は、それを呼び出してしまうと以後deleteができません。
newでつくった領域は同じDLLでないとdeleteできないと聞いたことがありますが、それが関係しているのでしょうか? 自分でhoge関数を作ったときは当然同じDLLだからうまくいくけど、OpenCVに渡して内部でvectorがresizeされると、それはOpenCVで確保された領域とみなされて、別のDLLだからエラー、とか?そんな馬鹿な・・・
以下、何となくにおうページ。
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200607/06070071.txthttp://msdn.microsoft.com/ja-jp/library/ms235460.aspxhttp://msdn.microsoft.com/ja-jp/library/f22wcbea.aspx
追記
コンパイラ オプション で /MT を /MD に変えたら若干直りました。OpenCVのDLLが /MD でつくられていたから、それに合わせないといけないのでしょう。ただし、まだ落ちるケースがいくつかあります。