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

将IntPtr转换为byte数组时抛出AccessViolationException的原因

AccessViolationException触发原因

你对Marshal.Copy的用法存在逻辑误解:
Marshal.Copy(IntPtr source, byte[] destination, int startIndex, int length)重载的执行逻辑是从source指向的非托管内存首地址开始,读取length个字节的连续内存数据,写入托管字节数组。这个方法要求传入的source必须是指向当前进程可访问、已分配的非托管内存块的起始地址,方法运行时会直接解引用这个指针去读对应内存的内容。

你的代码中传入的hWnd是窗口句柄,本质是一个作为系统对象标识的整数值,不是可读取的非托管内存块首地址。当Marshal.Copy尝试把hWnd存储的数值当作内存地址去读取数据时,要么该地址未被进程分配,要么属于受系统保护的不可读内存段,自然会触发访问违例异常。


正确实现方案

你的需求是把IntPtr变量本身存储的整数值转为字节数组,不需要解引用指针去读它指向的内存,可直接通过以下方式实现:

IntPtr hWnd = this.Handle;
int ptrSize = IntPtr.Size;
byte[] managedArray = new byte[ptrSize];

// 实现1:通过BitConverter直接转换整数值
if (ptrSize == 4)
{
    BitConverter.GetBytes(hWnd.ToInt32()).CopyTo(managedArray, 0);
}
else
{
    BitConverter.GetBytes(hWnd.ToInt64()).CopyTo(managedArray, 0);
}

// 实现2:通过Marshal直接拷贝结构体值(不需要解引用IntPtr指向的内存)
GCHandle handle = GCHandle.Alloc(managedArray, GCHandleType.Pinned);
try
{
    Marshal.StructureToPtr(hWnd, handle.AddrOfPinnedObject(), false);
}
finally
{
    handle.Free();
}

核心区分:

  • 要拷贝指针指向的内存内容时,才使用Marshal.Copy,且必须保证指针指向合法可访问的、长度满足要求的非托管内存
  • 要获取指针本身存储的地址值的字节表示时,不要解引用指针,直接对IntPtr存储的数值做转换即可

内容的提问来源于stack exchange,提问作者c00000fd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 18:36:25