2011-07-22 6 views
1

私はスタックオーバーフローの質問Marshaling unmanaged char** to managed string[]からコードをテストし、うまくいきます。Unicode文字列とFreeHGlobalの問題?

これをUnicodeに変換しようとしましたが、「ハンドルが無効です」というメッセージが表示されるようになりました。どうして?

私の修正コード:

_declspec(dllexport) void TestArray(wchar_t** OutBuff, int Count, int MaxLength) 
{ 
    for(int i=0; i<Count; i++) 
    { 
     wchar_t buff[25]; 
     _itow(i, buff, 10); 
     wcsncpy(OutBuff[i], buff, MaxLength); 
    } 
} 

とC#ラッパー:

class Program 
{ 
    [DllImport("Native.dll", EntryPoint = "[email protected]@[email protected]", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] 
    private static extern void TestArray([MarshalAs(UnmanagedType.LPArray)] 
    IntPtr[] OutBuff, int Count, int MaxLength); 

    static void Main(string[] args) 
    { 
     int count = 10; 
     int maxLen = 50; 
     IntPtr[] buffer = new IntPtr[maxLen]; 
     for (int i = 0; i < count; i++) 
      buffer[i] = Marshal.AllocHGlobal(maxLen); 

     TestArray(buffer, count, maxLen); 

     string[] output = new string[count]; 
     for (int i = 0; i < count; i++) 
     { 
      output[i] = Marshal.PtrToStringUni(buffer[i]); 
      Marshal.FreeHGlobal(buffer[i]); // Crash is here, when count is 1. 
      Console.WriteLine(output[i]); 
     } 
     Console.ReadKey(); 
    } 
} 

答えて

2

あなたはWindowsのヒープマネージャーにバグをキャッチすることができて幸運です。あなたはVistaまたはWindows 7を使用している必要があります。それは微妙なもので、wcsncpy()を使用していないと簡単に見逃してしまいます。問題は、文字列にmaxLen バイトを割り当てたことです。しかし、maxLen 文字をに割り当てる必要があります。 Unicode文字列を使用するときと同じではなく、1文字は2バイトです。あなたはまた、バッファ割り当てが間違っています。修正:

 IntPtr[] buffer = new IntPtr[count]; // NOTE: not maxLen 
     for (int i = 0; i < count; i++) 
      buffer[i] = Marshal.AllocHGlobal(maxLen * sizeof(Char)); 

ヒープの破損は、wcsncpy()の働きにより発生します。 wcscpy_s()とは異なり、バッファの残りの部分を0で埋めます。バッファーが小さすぎるため、ヒープを上書きして破損させます。 Windowsは、内部ヒープ構造が危険にさらされていることに気付いたときにステップインしました。

0

あなたはIntPtr配列を渡され、ネイティブ関数(へのポインタのポインタとして扱う)で直接修正。 IntPtrmanaged worldからのものであるため、直接修正により破損しているため、ハンドルが無効です。

+0

これはANSIバージョンで動作しました。直接の変更が破損を引き起こす可能性がある場合、言語間で文字列の動的配列を渡すコードを書き直すにはどうすればよいですか? – Assaf