You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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签名,使用适配平台位数的类型:

  1. 将GetProcessHeap的返回类型和HeapAlloc的hHeap参数改为IntPtr,它会自动根据32/64位系统调整大小。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 11:17:15