这是我的代码:
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,true);将第三个参数设置为true.这意味着系统将尝试释放最后为ptrStruct分配的内存.但是当第一次调用方法Show()时,没有为该结构分配内存(ptrStruct = IntPtr.Zero).因此系统将尝试释放位于零指针的内存.当然它会引发异常. Windows XP只是忽略了这一点,但Windows 7却没有.
这是最好的解决方案恕我直言:
Marshal.StructuretoPtr(ebt,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(); }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。