由Marshal.StructureToPtr引起的System.AccessViolation

时间:2012-03-27 13:20:06

标签: c# .net exception-handling marshalling

我在我的应用程序中使用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 个答案:

答案 0 :(得分:3)

并不像一些观察结果那么真实,但是评论太长了,所以:

  1. 如果您想返回代表IntPtr的{​​{1}},请使用null;这就是它的全部目的。

  2. IntPtr.Zero类有一个IntPtr方法,可以为现有的Add添加偏移量,这比您正在做的更安全。

  3. 由于您刚刚分配了全局缓冲区,并且尚未包含托管引用,因此您应该继续将IntPtr传递给false;无论如何,没有任何东西可以免费

  4. 您能准确说出此代码的哪一行产生访问冲突吗?

答案 1 :(得分:2)

我不确定导致访问冲突的原因,但是这一行:

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));
}

答案 2 :(得分:0)

你在64位上运行吗?当然,以下代码将失败:buffer.ToInt32()

完成缓冲后,您还应该调用FreeHGlobal。将参数保留为false