.NET Core 6调用kernel32的HeapAlloc触发访问违例的解决方法
问题解决:.NET Core 6中调用HeapAlloc引发System.AccessViolationException
问题根源
你的代码在.NET Framework中正常但在.NET Core 6中出错,核心原因是平台调用(P/Invoke)的类型不匹配,导致64位进程下堆句柄被截断:
GetProcessHeap返回的是Windows API中的HANDLE类型,在32位系统上占4字节(对应C#的int),但在64位系统上占8字节(对应C#的IntPtr)。- .NET Core默认以AnyCPU编译,在64位系统上会运行64位进程,此时用
int存储HANDLE会直接截断高4字节,得到无效的堆句柄。调用HeapAlloc时传入无效句柄,就会触发内存访问违规异常。 - 而.NET Framework项目可能默认编译为32位,
int刚好能容纳HANDLE,所以不会出问题。
修复方案
修正P/Invoke签名,使用适配平台位数的类型:
- 将
GetProcessHeap的返回类型和HeapAlloc的hHeap参数改为IntPtr,它会自动根据32/64位系统调整大小。 HeapAlloc的size参数对应Windows API的SIZE_T,建议使用UIntPtr(或.NET 5+的nuint)来匹配无符号的内存大小类型。
修正后的代码:
[DllImport("kernel32")] public static extern IntPtr GetProcessHeap(); [DllImport("kernel32")] public static extern void* HeapAlloc(IntPtr hHeap, uint flags, UIntPtr size); private static IntPtr _heap = GetProcessHeap(); public static void* Alloc(int size) { if (size < 0) throw new ArgumentOutOfRangeException(nameof(size)); UIntPtr sizePtr = (UIntPtr)size; void* result = HeapAlloc(_heap, 0x00000008, sizePtr); if (result == null) throw new OutOfMemoryException(); return result; }
额外说明
- 如果你需要兼容更早的.NET版本,也可以用
int作为size参数,但要注意内存大小不能超过int的最大值(2GB),否则会溢出。使用UIntPtr或nuint是更规范的写法,能匹配Windows API的原生类型。 - 确保你的.NET Core项目编译配置和运行环境的位数一致,避免因类型截断导致的内存问题。
内容的提问来源于stack exchange,提问作者Varooneh
相关产品推荐
相关产品推荐

