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

C#传递coordpt结构体锯齿数组到C++ DLL异常排查与实现优化

问题解答

1 现有代码的错误分析

你给出的代码存在多处直接导致内存访问异常的错误,具体如下:

  • 结构体定义严重错误
    你把C中值类型的coordpt定义成了C#的引用类型class,封送时会多一层指针,完全不符合C的内存布局。其次LayoutKind.Explicit的偏移值设置错误:double类型占8字节,x偏移为0,y的偏移应该是8,你写FieldOffset(1)会导致两个字段内存完全重叠,传递的数据全部错乱。
    正确的结构体定义如下:
    [StructLayout(LayoutKind.Sequential)]
    public struct coordpt
    {
        public double x;
        public double y;
    
        public coordpt(double x, double y)
        {
            this.x = x;
            this.y = y;
        }
    }
    
  • 调用约定可能不匹配
    头文件中定义如果是__WATCOMC__编译环境,函数调用约定是__stdcall,你当前DllImport写的是CallingConvention.Cdecl,如果DLL是Watcom编译器生成的,调用约定不匹配会直接导致栈不平衡,触发内存访问错误,可先改为CallingConvention.StdCall测试。
  • StructureToPtr参数错误
    Marshal.StructureToPtr的第三个参数fDeleteOld你传了true,但你通过AllocCoTaskMem申请的是全新内存,里面没有需要释放的旧结构数据,传true会让CLR尝试释放未初始化内存的内容,直接触发访问违规,该参数应该传false。
  • 其他隐患
    直接对IntPtr做整数加法在32位运行环境下可能溢出,建议使用IntPtr.Add计算偏移;你当前只申请了非托管内存,没有对应的释放逻辑,会导致内存泄漏。

上述错误均会直接触发你遇到的AccessViolationException异常。

2 更简便的锯齿数组传递实现

如果允许使用unsafe代码,可以省略逐个拷贝结构体的步骤,直接固定数组内存传递,实现更简单、性能更高:

// 调用逻辑示例
unsafe
{
    GCHandle[] rowHandles = new GCHandle[inputArrayOfArrays.Length];
    IntPtr[] ptrArr = new IntPtr[inputArrayOfArrays.Length];
    for (int i = 0; i < inputArrayOfArrays.Length; i++)
    {
        // 固定每一行的数组内存
        rowHandles[i] = GCHandle.Alloc(inputArrayOfArrays[i], GCHandleType.Pinned);
        ptrArr[i] = rowHandles[i].AddrOfPinnedObject();
    }
    // 调用DLL函数
    int result = CPlusPlusFunction(ptrArr, NumberOfArrays, arrayContainesTheSizeOfEachArray);
    // 释放固定句柄
    foreach (var handle in rowHandles)
    {
        handle.Free();
    }
}

这种方式不需要手动申请、拷贝内存,依托GC的固定机制实现,逻辑更简洁,也不会有内存泄漏风险,前提是C++函数不会在返回后仍持有传入的指针地址。
如果不能使用unsafe代码,修复现有封送方法的错误后也可正常使用,注意调用完DLL函数后要逐个释放你申请的CoTaskMem内存即可。

内容的提问来源于stack exchange,提问作者Eran.G

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 07:45:05