winform引用C++DLL,错误代码为 0xc0000005。此错误可能是 CLR 中的 bug,或者是用户代码的不安全部分或不可验证部分中的 bug

一個人過得快樂 2018-04-17 11:49:36
出错的具体信息为 :

运行时遇到了错误。此错误的地址为 0x5f6996b5,在线程 0x1f68 上。错误代码为 0xc0000005。此错误可能是 CLR 中的 bug,或者是用户代码的不安全部分或不可验证部分中的 bug。此 bug 的常见来源包括用户对 COM-interop 或 PInvoke 的封送处理错误,这些错误可能会损坏堆栈。

我在调用C++的DLL,解析NetCDF文件,获取了float[, ,] 多维数组,这个数组的值获取正常。
之后我遍历数组,加上对数据的处理,根据索引从数组取值没有问题,但是循环多次后,一些简单的代码,就会引起这个错误,比如list.toArray,DataTable.Rows.Add,Math.sqrt等等。

如果不解析,我取到了数组,再简单的写成一个新的NC文件时,第一遍不会报错,第二遍就会卡住,然后也提示这个错误。

DLL的引用我是这么写的。

[DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int nc_open(string path, CreateMode mode, out int ncidp);

Cdecl表示调用方清理堆栈,是否是因为内存清理方面的问题呢,因为我对这个不是很懂,想请教大家。
...全文
3049 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
cyyslq 2020-12-25
  • 打赏
  • 举报
回复
遇到同样问题是,楼主是怎么解决的
weixin_38180731 2020-12-17
  • 打赏
  • 举报
回复
解决了么,遇到同样的问题。
sunylf 2018-04-18
  • 打赏
  • 举报
回复
u*u+V*V的值过大,引起的吧?
  • 打赏
  • 举报
回复
引用 4 楼 q644415569 的回复:
检查一下参数,很可能是传到底层的参数类型错误, 数组长度错误 等问题," 获取了float[, ,] 多维数组" 这里很可能有问题,即使你成功获取了一组数据,不能保证C++那边数据不会有溢出.检查下看
是这样啊,我再检查看看。
  • 打赏
  • 举报
回复
继续求助,问题还是没解决。
  • 打赏
  • 举报
回复
引用 6 楼 sunylf 的回复:
u*u+V*V的值过大,引起的吧?
应该不是,报错的那句话上面的U和V我都看到数字了,然后用这个数字在测试窗体里写了,直接就运行成功了。而且每次出现错误的索引不同,如果是数据的问题,不应该有的时候能过去,有时候又报错吧。
  • 打赏
  • 举报
回复
引用 4 楼 q644415569 的回复:
检查一下参数,很可能是传到底层的参数类型错误, 数组长度错误 等问题," 获取了float[, ,] 多维数组" 这里很可能有问题,即使你成功获取了一组数据,不能保证C++那边数据不会有溢出.检查下看
我测了一下,应该不是的,我增加了参数的数量,返回的数组末端就多了很多为0未处理的数据,换了类型直接会报错的。因为我能看到NC文件里的数据,所以我调试时用即时窗口看了下,应该是正确的。
蜗牛慢慢趴 2018-04-17
  • 打赏
  • 举报
回复
检查一下参数,很可能是传到底层的参数类型错误, 数组长度错误 等问题," 获取了float[, ,] 多维数组" 这里很可能有问题,即使你成功获取了一组数据,不能保证C++那边数据不会有溢出.检查下看
  • 打赏
  • 举报
回复
自顶一下,继续求助。
  • 打赏
  • 举报
回复
引用 1 楼 xian_wwq 的回复:
可以将地址转为不被垃圾收集器清理的固定地址。 可以参考这个示例

bool  FireSDK_GetDeviceList(int loginid, DEVICE ** devinfo, int * devcount, CHANNEL ** chinfo, int * chcount);  

struct devinfo
{
public string devID;  
public string devName;
   
//……
}
//调用
devinfo di = new devinfo();
di.devID = "KD0000299";
di.devName="myDevice";

GCHandle C_di = GCHandle.Alloc(di, GCHandleType.Pinned);
FireSDK_GetDeviceList(loginid,out C_di.AddrOfPinnedObject(),...); 
C_di.Free();
没太理解您的意思,我以为是我调用C++的DLL,然后内存没有被清理,所以导致内存溢出,因为我在内存配置较低的电脑,第一次取数据后,循环处理就会出这个问题。

 public static partial class NetCDF
    {
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_open(string path, CreateMode mode, out int ncidp);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_create(string path, CreateMode mode, out int ncidp);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_close(int ncidp);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_sync(int ncid);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_enddef(int ncid);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_redef(int ncid);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern string nc_strerror(int ncerror);

        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_inq(int ncid, out int ndims, out int nvars, out int ngatts, out int unlimdimid);

        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_def_var(int ncid, string name, NcType xtype, int ndims, int[] dimids, out int varidp);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_inq_var(int ncid, int varid, StringBuilder name, out NcType type, out int ndims, int[] dimids, out int natts);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_inq_varids(int ncid, out int nvars, int[] varids);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_inq_vartype(int ncid, int varid, out NcType xtypep);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_inq_varnatts(int ncid, int varid, out int nattsp);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_inq_varid(int ncid, string name, out int varidp);

        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_inq_ndims(int ncid, out int ndims);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_inq_nvars(int ncid, out int nvars);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_inq_varname(int ncid, int varid, StringBuilder name);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_inq_varndims(int ncid, int varid, out int ndims);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_inq_vardimid(int ncid, int varid, int[] dimids);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_inq_var_fill(int ncid, int varid, out int no_fill, out object fill_value);


        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_inq_natts(int ncid, out int ngatts);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_inq_unlimdim(int ncid, out int unlimdimid);
        [DllImport("netcdf4.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int nc_inq_format(int ncid, out int format);
}

 public bool ConvertNetCDF_UV(string input_path, string output_path)
        {
                int re = NetCDF.nc_open(input_path, NetCDF.CreateMode.NC_NOWRITE, out i);
                NetCDF.nc_inq_varid(i, "u", out varid);   //获取输入列的序列
                NetCDF.nc_inq_var(i, varid, name, out type, out ndims, dimids, out natts);  //用来查询列的属性,这里主要拿来看维度的,其他的用不上
                
                float[, ,] tempdata_u = new float[depth_length, lat_length, lon_length];
                NetCDF.nc_get_var_float(i, varid, tempdata_u);  //获取数据没有问题


                float[, ,] tempdata_v = new float[depth_length, lat_length, lon_length];
                NetCDF.nc_inq_varid(i, "v", out varid);   //获取输入列的序列
                NetCDF.nc_get_var_float(i, varid, tempdata_v);  //获取数据

                NetCDF.nc_close(i);

                 for (int j = 0; j < depth_length; j++)
                    {
                        float[,] values_float = new float[lat_length, lon_length];
                        for (int k = 0; k < lat_length; k++)
                        {
                            for (int l = 0; l < lon_length; l++)
                            {
                                  float u = tempdata_u[j, k, l];   //取数字没有问题
                                  float v = tempdata_v[j, k, l];   //取数字没有问题
                                  string val = Math.Sqrt(u * u + v * v).ToString();    //在这里就会报错,而且不是每次都报错,执行到三维数组第6次开始就可能报错,而且每次报错的索引还都不一样。
                             }
                        }
                    }
}
xian_wwq 2018-04-17
  • 打赏
  • 举报
回复
可以将地址转为不被垃圾收集器清理的固定地址。 可以参考这个示例

bool  FireSDK_GetDeviceList(int loginid, DEVICE ** devinfo, int * devcount, CHANNEL ** chinfo, int * chcount);  

struct devinfo
{
public string devID;  
public string devName;
   
//……
}
//调用
devinfo di = new devinfo();
di.devID = "KD0000299";
di.devName="myDevice";

GCHandle C_di = GCHandle.Alloc(di, GCHandleType.Pinned);
FireSDK_GetDeviceList(loginid,out C_di.AddrOfPinnedObject(),...); 
C_di.Free();

110,499

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧