System.AccessViolation из-за Marshal.StructureToPtr - PullRequest
1 голос
/ 27 марта 2012

Я использую инструмент вечеринки Trhird в своем приложении.В некоторых системах я получаю ошибку System.AccessViolation.Хотя, через код я не могу воспроизвести проблему.Но в производственной среде он действительно воспроизводится через некоторое время.

У меня есть сомнения по поводу следующего кода

public static IntPtr TestMarshalToPointer(object value, System.Type type, int length)
{
    int offset = 0;
    int size = Marshal.SizeOf(type) * length;
    IntPtr buffer;

    try
    {
        buffer = Marshal.AllocHGlobal(size);

        for (var index = 0; index < length; index++)
        {
            Marshal.StructureToPtr(value, new IntPtr(buffer.ToInt32() + offset), false);
            // Its written on MSDN that passing false can lead to memory leak. Please guide , should i need to pass true and how it will affect**
            offset += Marshal.SizeOf(type);
        }
    }
    catch
    {
        buffer = (IntPtr)null;
    }

    return buffer;
}

Ответы [ 3 ]

3 голосов
/ 28 марта 2012

Не совсем ответ, как некоторые наблюдения, но он слишком длинный для комментария, поэтому:

  1. Если вы хотите вернуть IntPtr, который представляет null, используйте IntPtr.Zero;в этом вся его цель.

  2. В классе IntPtr есть метод Add, который добавляет смещение к существующему IntPtr, которое безопаснее того, что вы делаете.

  3. Поскольку вы только что выделили свой глобальный буфер, и в нем еще нет управляемой ссылки, вы должны продолжать передавать false в StructureToPtr;в любом случае нет ничего, что можно было бы освободить

Вы можете точно сказать, какая строка этого кода вызывает нарушение прав доступа?

2 голосов
/ 28 марта 2012

Я не уверен, что вызывает нарушение прав доступа, но эта строка:

Marshal.StructureToPtr(value, new IntPtr(buffer.ToInt32() + offset), false);

Кажется подозрительным.Замена кода с более разумным использованием класса IntPtr может помочь:

buffer = Marshal.AllocHGlobal(size);
offset = buffer;
for (var index = 0; index < length; index++)
{
    Marshal.StructureToPtr(value, offset, false);
    IntPtr.Add(offset, Marshal.SizeOf(type));
}
0 голосов
/ 28 марта 2012

Вы работаете на 64 бит? Следующий код, конечно, завершится ошибкой: buffer.ToInt32()

Вам также следует вызвать FreeHGlobal после того, как вы закончили работу с буфером. Оставьте параметр как false.

...