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

C#通过PInvoke释放C++分配的二维double数组时程序崩溃如何解决

崩溃核心原因
  • 首要原因:传递给释放函数的指针已经是非法的偏移后地址
    你编写的FromNative方法使用了ref IntPtr data作为参数,循环中每次执行data = (IntPtr)(data.ToInt64() + IntPtr.Size)直接修改了外部传入的jointAreaPointer原始值。读取完全部数据后,jointAreaPointer已经不再指向C分配的double**数组起始地址,而是偏移了numberOfPairs * IntPtr.Size的野指针。将野指针传入C释放函数后,访问arr[i]直接触发非法内存访问,导致崩溃。
  • 次要潜在问题:P/Invoke的bool类型封送不匹配
    C#默认将bool类型封送为4字节的Win32 BOOL,而C++端的bool是1字节类型,参数传递时会出现栈偏移,也可能触发崩溃。
修复方案

1. 修正FromNative方法,不要修改原始指针

两种修改方式二选一:

  • 去掉多余的ref关键字,你不需要修改外部的原始指针,完全没必要用ref:
// 去掉参数的ref修饰
public static double[][] FromNative(IntPtr data, int m, int[] n)
{
    var matrix = new double[m][];
    IntPtr currentPtr = data; // 用临时变量做偏移,不修改原始指针
    for (int i = 0; i < m; i++)
    {
        int c = n[i] * 3;
        matrix[i] = new double[c];
        Marshal.Copy(Marshal.ReadIntPtr(currentPtr), matrix[i], 0, c);
        currentPtr = (IntPtr)(currentPtr.ToInt64() + IntPtr.Size);
    }
    return matrix;
}
// 调用时也不需要加ref
double[][] polylinePoints = FromNative(jointAreaPointer, numberOfPairs, jointAreaCountPointerFlatArray);
  • 如果你一定要保留ref修饰,就用临时变量做偏移,不要修改入参的data。

2. 修正P/Invoke的bool类型封送

给C#端的bool参数加封送标记,匹配C++的1字节bool:

[DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern void ReleaseNestedDouble(IntPtr arr, int count, [MarshalAs(UnmanagedType.I1)] bool isArray = true);

3. 额外校验项

确保C++端分配内存时,外层double**数组和内层每个double*数组都是用new[]分配的,和delete[]对应,不能混用malloc/free或者new/delete。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 00:09:01