読者です 読者をやめる 読者になる 読者になる

ラッパー用ファクトリ関数で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 でつくられていたから、それに合わせないといけないのでしょう。ただし、まだ落ちるケースがいくつかあります。