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

C#调用含void*成员结构体数组的C DLL时遇内存访问错误

问题:C#调用C编写的DLL函数时触发访问违规异常

C端函数与结构体定义

C DLL中的函数签名及结构体定义如下:

unsigned long MyFunc(mystruct *arr, unsigned long arrLen);

typedef struct mystruct {
  unsigned long type;
  void* val;
  unsigned long valLen;
} mystruct;

其中type用于标识val的实际指针类型,valLen是val指向值的字节大小。

C#端声明

C#中对应的结构体与P/Invoke声明:

[StructLayout(LayoutKind.Sequential)]
public struct mystruct{
  public uint type;
  public IntPtr val;
  public uint valLen;
} 

[DllImport("mydll.dll")]
public static extern uint MyFunc(mystruct[] arr, uint arrLen);

错误信息

调用时触发以下异常:

Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

测试场景与排查结果

  • 尝试传递3个元素的数组:分别对应C的unsigned long*类型的uint、unsigned char的byte、char*的byte数组;仅传递单个uint元素的数组时也会报错。
  • 注释DLL中解引用val的代码后,调用无错误;传递null数组时也无错误,因此问题出在指针传递方式上。

已尝试的两种传递方式

0- 手动固定托管内存

mystruct[] arr = new mystruct[3];
arr[0].type = 0;
uint my_uint = 10;
GCHandle handle_uint = GCHandle.Alloc(my_uint, GCHandleType.Pinned);
arr[0].val = handle_uint.AddrOfPinnedObject();
arr[0].valLen = sizeof(uint);

arr[1].type = 1;
byte my_byte= 1;
GCHandle handle_byte = GCHandle.Alloc(my_byte, GCHandleType.Pinned);
arr[1].val= handle_byte.AddrOfPinnedObject();
arr[1].valLen= sizeof(byte);

arr[2].type = 2;
byte[] my_byte_arr = new byte[32];
for (int i = 0; i < 32; i++) {
    my_byte_arr[i] = 255;
}
GCHandle handle_byte_arr = GCHandle.Alloc(my_byte_arr, GCHandleType.Pinned);
arr[2].val = handle_byte_arr.AddrOfPinnedObject();
arr[2].valLen = (uint) my_byte_arr.Length;

MyFunc(arr, (uint) arr.Length);
handle_uint.Free();
handle_byte.Free();
handle_byte_arr.Free();

1- 手动分配非托管内存(仅展示uint的情况)

mystruct[] arr = new mystruct[1];
arr[0].valLen = sizeof(uint);
arr[0].type = 0;
arr[0].val = Marshal.AllocCoTaskMem((int) arr[0].valLen);

Marshal.WriteInt32(arr[0].val, 10);
MyFunc(arr, (uint) arr.Length);
Marshal.FreeCoTaskMem(arr[0].val);

补充说明

曾参考相关问题,但现有方案不适用:能正常调用DLL的其他函数,仅该函数在解引用val时出错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 03:10:29