2011-09-12 15 views
1

私はC#アプリケーションを作成していますが、その効率を上げるためにC++にする必要があります。 C++での関数は次のようにエクスポートされます。C#バーチャルマシンで書込み保護された配列

extern "C" __declspec(dllexport) int fastSegment(char*, int, int);

私は次のようにC#でこの機能をインポート:

私が処理したい画像には、次のように呼ばれている
[DllImport(_dllname, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] 
static private extern bool fastSegment(byte[] img, int width, int height); 

fastSegment(image, 640, 480); 

imageは正しいサイズです。私はメモリを浪費して新しい配列を割り当てたくないので、C++関数で配列を直接変更しました。

どうしますか?死のブルースクリーン。以前はWindows 7でそれを見たことはありませんでした。

私の機能はテスト目的でimage[0],image[1]image[2]と書いてありますが、これを削除しても問題ありません。

私の推測では、仮想マシンのメモリを保護していることですが、私はそれが奇妙な私はちょうどそれに書き込むことはできません、または仮想マシンは、単に例外をスローしなかったことを見つけます。そのバッファの保護を解除する方法はありますか?または新しいバッファを割り当てる必要がありますか?

編集:

データ書き込み時にプログラムが実行されます。この突然の墜落の原因は何でしたか?

+1

NTモードのOSでは、ユーザーモードコードではBSODを起動できません。何とかwin32k.sysをクラッシュさせてしまったのだろうか... windbgのカーネルダンプファイルを見ると、このクラッシュについて何か教えてくれるだろう。 (詳細については、これらの用語をgoogleを参照してください) – asveikau

答えて

2

ガベージコレクタは、管理対象データの移動を許可されています。ネイティブコードはこれを検出できないため、間違ったメモリアドレスに書き込む可能性があります。しかし、.NETランタイムに配列を移動しないように指示することができます。例えば。

GCHandle handle = GCHandle.Alloc(image, GCHandleType.Pinned); 
try 
{ 
    fastSegment(handle.AddrOfPinnedObject(), 640, 480); 
} 
finally 
{ 
    // make sure to free the handle to avoid leaks! 
    handle.Free(); 
} 

編集GCHandleクラスでこれが唯一の方法ですが、私はそれが問題を示していると思います。 Marshaling between Managed and Unmanaged Code

+0

これは、BSODがなぜ起こったのかを説明することができます。ありがとう:)クラッシュが純粋にランダムなので、このバージョンが動作するかどうかはテストするのが難しいでしょう。 – wormsparty

2

これはできません。この場合、配列は読み込み専用になります。 C#の配列をネイティブで変更する場合は、ポインタとしてマーシャリングする必要があります。
マイクロソフトからexampleをご覧ください。
これがなぜ必要なのかについての説明もあります。

0

データがGCによって移動している可能性がありますが、アプリケーションを実行するたびにクラッシュした場合、その可能性はほとんどありません。次のいずれかを試してください。

[DllImport(_dllname, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] 
private static extern bool fastSegment(IntPtr img, int width, int height); 
[ReliabilityContract(Consistency.MayCorruptProcess, Cer.None)] 
static void FastSegment(byte[] data, int width, int height) 
{ 
    var length = width * height; 
    var ptr = Marshal.AllocHGlobal(width * height); 
    try 
    { 
     Marshal.Copy(data, 0, ptr, length); 
     fastSegment(ptr, width, height); 
     Marshal.Copy(ptr, data, 0, length); 
    } 
    finally 
    { 
     Marshal.FreeHGlobal(ptr); 
    } 
} 
// ---- OR ---- 
[DllImport(_dllname, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] 
private static extern bool fastSegment(IntPtr img, int width, int height); 
[ReliabilityContract(Consistency.MayCorruptProcess, Cer.None)] 
static void FastSegment(byte[] data, int width, int height) 
{ 
    var handle = GCHandle.Alloc(data, GCHandleType.Pinned); 
    try 
    { 
     fastSegment(handle.AddrOfPinnedObject(), width, height); 
    } 
    finally 
    { 
     handle.Free(); 
    } 
} 
// ---- OR ---- 
[DllImport(_dllname, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] 
private static unsafe extern bool fastSegment(byte* img, int width, int height); 
[ReliabilityContract(Consistency.MayCorruptProcess, Cer.None)] 
static void FastSegment(byte[] data, int width, int height) 
{ 
    unsafe 
    { 
     fixed (byte* dataPinned = data) 
     { 
      fastSegment(dataPinned, width, height); 
     } 
    } 
} 
関連する問題