Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/89.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 位于'的访问冲突异常;Marshal.StructureToPtr';在Windows 7+;中。NET4.0(WindowsXP+;.NET3.5运行良好)_C#_.net_Marshalling_Unmanaged - Fatal编程技术网

C# 位于'的访问冲突异常;Marshal.StructureToPtr';在Windows 7+;中。NET4.0(WindowsXP+;.NET3.5运行良好)

C# 位于'的访问冲突异常;Marshal.StructureToPtr';在Windows 7+;中。NET4.0(WindowsXP+;.NET3.5运行良好),c#,.net,marshalling,unmanaged,C#,.net,Marshalling,Unmanaged,这是我的密码: internal void Show() { if (Parent == null) throw new NullReferenceException(); EDITBALLOONTIP ebt = new EDITBALLOONTIP(); ebt.cbStruct = Marshal.SizeOf(ebt); ebt.pszText = Text; ebt.pszTitle = Caption; ebt.ttiI

这是我的密码:

internal void Show()
{
    if (Parent == null)
        throw new NullReferenceException();
    EDITBALLOONTIP ebt = new EDITBALLOONTIP();
    ebt.cbStruct = Marshal.SizeOf(ebt);
    ebt.pszText = Text;
    ebt.pszTitle = Caption;
    ebt.ttiIcon = (int)Icon;
    IntPtr ptrStruct = Marshal.AllocHGlobal(Marshal.SizeOf(ebt));
    Marshal.StructureToPtr(ebt, ptrStruct, true); // Here we go.
    // Access violation exception in Windows 7 + .NET 4.0
    // In Windows XP + .NET 3.5, it works just fine.

    // ... Some other code ...

    Marshal.FreeHGlobal(ptrStruct);
}
结构如下:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct EDITBALLOONTIP
{
    internal int cbStruct;
    internal string pszTitle;
    internal string pszText;
    internal int ttiIcon;
}
为什么这在Windows XP+.NET 3.5中运行良好,而在Windows 7+.NET 4.0中引发异常?可能是CharSet的麻烦

================================================================================== 解答与解释 如您所见,Marshal.StructureToPtr(ebt、ptrStruct、true);将第三个参数设置为true。这意味着系统将尝试释放最后分配给ptrStruct的内存。但是当第一次调用方法
Show()
时,没有为该结构分配内存(ptrStruct=IntPtr.Zero)。所以系统将尝试释放位于零指针的内存。当然,这会引发一个例外。Windows XP只是忽略了这一点,但Windows 7没有

以下是IMHO的最佳解决方案:

   Marshal.StructureToPtr(ebt, ptrStruct, false);
   //Working...
   //Free resources
   Marshal.FreeHGlobal(ptrStruct);
我不想在这里添加答案,因为您已经解决了您的问题,我将说的不会为您的问题提供任何答案,但它不适合作为注释,因为我提供了一些代码。 所以我不得不把它贴在这里作为回答

您可能已经知道了(并且没有这样编写,因此您的问题中的代码更简单),但我只想说,在分配非托管内存时,应该在任何地方使用的最佳实践是将代码封装在try/finally块中,以确保始终释放内存,即使引发异常:

private static void Test()
{
    IntPtr ptrStruct = IntPtr.Zero;

    try
    {
        Marshal.AllocHGlobal(0x100);

        // Some code here
        // At some point, an exception is thrown
        throw new IndexOutOfRangeException();
    }
    finally
    {
        // Even if the exception is thrown and catch
        // from the code that calls the Test() method,
        // the memory will be freed.
        if (ptrStruct != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(ptrStruct);
        }
    }
}

try
{
    Test();
}
catch (IndexOutOfRangeException)
{
    // Catches the exception, so the program won't crash
    // but it'll exit the Test() method, so the try/finally
    // ensures it won't leave without freeing the memory
    Debugger.Break();
}

尝试使用
PackSize=1
。您可以提供“已解决”部分作为您自己问题的答案,这与您要使用的系统一致,而不是在其中留下正式的“未答复”帖子和解决方案。Windows 7有一个更严格的内存管理器,它无法忍受程序试图向HeapFree()传递无效指针。XP只是忽略了它。也就是说,在您的情况下不应该发生这种情况,因为AllocHGlobal()返回零初始化内存。这里还有别的事。。。