Строка Unicode и проблема FreeHGlobal? - PullRequest
1 голос
/ 22 июля 2011

Я проверил код из вопроса переполнения стека Маршалинг неуправляемого символа ** в управляемую строку [] , и он хорошо работает.

Я попытался преобразовать его в 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 = "?TestArray@@YAXPAPA_WHH@Z", 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 ]

2 голосов
/ 22 июля 2011

Вам повезло получить диспетчер кучи Windows, чтобы поймать ошибку, вы должны использовать Vista или Windows 7. Он тонкий, и его было бы легко пропустить, если бы вы не использовали wcsncpy ().Проблема в том, что вы выделили maxLen bytes для строки.Но вам нужно выделить maxLen символов .Не то же самое, когда вы используете строки Unicode, один символ составляет два байта.Вы также неправильно распределили буфер.Исправление:

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

Повреждение кучи происходит из-за того, как работает wcsncpy ().If заполняет остаток буфера нулями, в отличие от wcscpy_s ().Так как ваш буфер слишком мал, это перезаписывает и повреждает кучу.Windows вошла, когда заметила, что внутренняя структура кучи была взломана.

0 голосов
/ 22 июля 2011

Вы передали массив IntPtr и изменили его непосредственно в собственной функции (рассматривая его как указатель на указатель).Поскольку IntPtr из управляемого мира , прямое изменение повредило его - и, следовательно, дескриптор недействителен.

...