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

C#通过DllImport传数组到C++ DLL删除时报System.AccessViolationException

问题根因与修复方案

触发System.AccessViolationException的核心原因是C++侧尝试删除的指针不属于当前模块CRT堆的合法可释放范围,可按以下方向逐一排查修复:

  • 内存分配释放一致性校验:所有需要C侧delete释放的Game实例,必须由当前C DLL导出的分配接口(如CreateGame()这类自定义导出函数)创建,确保内存分配和释放处于同一个CRT堆中。如果Game实例是C#侧托管内存分配、或是其他模块分配的内存,直接用当前DLL的delete释放必然触发访问越界。
  • DllImport签名匹配校验:C#侧的函数声明必须和C++导出完全匹配,尤其注意调用约定和数组封送规则,参考正确声明如下:
    // 注意调整CallingConvention和DLL文件名与实际情况一致
    [DllImport("你的DLL名称.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern void empty([In] IntPtr[] gamePtrArray, int index);
    
    C++默认导出的函数调用约定为Cdecl,如果C#侧未显式指定默认使用Stdcall,会导致参数压栈错乱,拿到的x[y]本身就是非法野指针。
  • 传递类型正确性校验:C参数Game* x[]本质是Game**类型,对应C#侧必须传递IntPtr数组(每个元素为C侧分配的Game实例指针),如果直接传递Game结构体数组,x[y]会被解析为结构体值而非合法指针,执行delete必然崩溃。
  • 下标合法性校验:传入的y值不能超过数组x的有效下标范围,越界访问拿到的非法指针执行释放操作也会触发访问异常。
  • 重复释放校验:确认x[y]对应的指针没有被提前释放过,建议每次释放后将对应位置的指针置为nullptr,避免二次释放问题。
  • 额外说明:你当前C代码中的try catch只能捕获标准C异常,无法捕获访问越界这类结构化异常,如果需要在C++侧拦截这类错误避免进程直接崩溃,需要给DLL开启/EHa结构化异常处理编译选项,但该操作无法解决根本问题,仅能做兜底容错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 00:45:03