C#调用非托管dll运行时随机报System.AccessViolationException

cardinal_508 2012-03-26 09:01:09
我写的C#程序有几个接口会频繁调用vc写的非托管dll,这个动态库之前就在用应该没什么大问题
而且程序在运行时也比较正常,但是当我在运行一段时间后,发现程序卡死了(系统呈现死机状态,屏幕保护时按键无法激活显示器),在我写demo测试接口时发现测试程序运行一段时间后程序报错误,错误信息如下:

See the end of this message for details on invoking
just-in-time (JIT) debugging instead of this dialog box.

************** Exception Text **************
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at Common.API.CLIENTStart.Invoke(CHANNELR& _pCHANNEL)
at Common.Monomer.Channel.Connect(IntPtr _hWnd)
at test_Cruse.Connect()
at test_Cruse.tmrCurse_Tick(Object sender, EventArgs e)
at System.Windows.Forms.Timer.OnTick(EventArgs e)
at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
我最初的考虑此问题的可能引发的原因是,系统用调用非托管dll时所传入的结构体中有以string声明的成员,在转入vcdll时需要转换,而且整个结构体在传输时不会被锁定,在调用dll接口时此结构体的内存发生了移动,所以我把string换成了定长的byte[] 但是demo依然会引发System.AccessViolationException异常,不知道有没有人遇到过!

最奇怪的是可能调用此接口50次都不会发生问题,也可能20-30次就会发生此异常,但是一开始运行程序的时候是没问题的。
...全文
2379 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
snakecopy 2013-05-27
  • 打赏
  • 举报
回复
楼主,此问题解决了吗?我也遇到此问题,求解!
snakecopy 2013-05-27
  • 打赏
  • 举报
回复
楼主,你提的问题解决了吗?我也遇到此问题,求解!
yangmin0611 2012-05-30
  • 打赏
  • 举报
回复
我也遇见这类问题,好纠结啊
cardinal_508 2012-03-27
  • 打赏
  • 举报
回复
我优化了dll部分代码,与此接口无关系,正在测试,暂时没有报错
WAN 2012-03-26
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 foreachif 的回复:]
非托管的C++代码可访问的内存应仅限于调用时封送的数据缓冲区
[/Quote]
说的是应该由调用方分配的数据内存。被调用的C++内自行申请的内存不受此限
WAN 2012-03-26
  • 打赏
  • 举报
回复
非托管的C++代码可访问的内存应仅限于调用时封送的数据缓冲区,包括调用时锁定的区域或AllocCoTaskMem(手动或自动)分配的区域
如产生了非法访问,要么是封送过程有错,要么是Dll本身的问题
WAN 2012-03-26
  • 打赏
  • 举报
回复
平台调用时数据复制使用的内存是Introp自动调用AllocCoTaskMem分配的,并在完成后自动调用FreeCoTaskMem释放。不属托管内存,不受GC控制
只要封送的过程是正确的,就不必担心垃圾回收会造成影响。而又有谁会在使用DllImport时考虑内存是否会被垃圾回收呢?一样用的好好的额~
cardinal_508 2012-03-26
  • 打赏
  • 举报
回复
这和dll应该关系不大,dll接口和传入结构体有关的只有memcpy这一个函数而已,应该不会有影响
http://topic.csdn.net/u/20081113/09/69F1C532-D1C6-4ED7-A2DD-C9851AC8BB1A.html
这个帖子中提到 由于非托管的代码试图访问CLR保护的内存引起的,在垃圾回收以后,垃圾回收器要压缩内存,这时有些内存块将要移动,这些内存是受到保护的
是不是这个问题呢????
WAN 2012-03-26
  • 打赏
  • 举报
回复
单纯由blittable类型构成的结构和数组是blittable的,但嵌套数组的结构不会是blittable的,在这里使用String和Byte[]没太大的区别
但是应该和这点没有关系,锁定只是作为一种优化的方式,不锁定,则会复制,与锁定相比只是开销较大而已
楼主最好贴一下代码,包括VC写的CLIENTStart函数体。这类错误往往是dll其本身有问题
冰镇宝贝321 2012-03-26
  • 打赏
  • 举报
回复
不会,可以帮顶不
cardinal_508 2012-03-26
  • 打赏
  • 举报
回复
补充一下CLIENTStart接口我传递的是结构体指针,使用ref CHANNELR的方式
我查询了一下如果使用引用类型封送的字段都是blittable类型如byte、int等时,封送拆收器将他锁定在托管内存中,而整个结构体中需要char数组,我一开始使用string时引发异常我担心是string不是blittable类型的问题,托管内存没有被锁定,所以我把string改为了byte[],因为只包含blittable的一维数组也被当做blittable类型,想排除此问题
WAN 2012-03-26
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 zhu_jiang 的回复:]
1.虽然timer控件也实现窗口句柄,timer控件也不能保证tick代码能否被完整执行
[/Quote]
但这不是说“当前的执行代码会被销毁”,仅仅是WM_TIMER
[Quote=引用 17 楼 zhu_jiang 的回复:]
2.Pinvoke并非原子性操作,存在被打断的可能性
[/Quote]
非要这么说也可以,但会被那个线程打断,自身?GC线程?还自动调用FreeCoTaskMem?
WAN 2012-03-26
  • 打赏
  • 举报
回复
需要测试的是当连续传入相同的或可控的数据内容时是否会引发错误
发现楼主的代码没有检查GetBytes返回的字节数是否超出了11个字节,也不确定hWnd是否合法,另外如果dll中仅以'\0'决定字符串的结束位置,则在C#中也要保证这一点。楼主没贴的那部分代码,也应该是相关的,不然传入的参数就没意义了,或者说是间接相关(pConInfor)。即使真的是完全与_pConInfor无关,也不是说就不可能是问题产生的原因
cardinal_508 2012-03-26
  • 打赏
  • 举报
回复
我写的demo只有一个计时器或线程在运行,并没有其他的工作在进行,也会有被打断的可能?
cardinal_508 2012-03-26
  • 打赏
  • 举报
回复
这样能排除是我C#上层调用的问题吗?
cardinal_508 2012-03-26
  • 打赏
  • 举报
回复
我换成了线程 出现了vc dll 错误
zhu_jiang 2012-03-26
  • 打赏
  • 举报
回复
1.虽然timer控件也实现窗口句柄,timer控件也不能保证tick代码能否被完整执行
2.Pinvoke并非原子性操作,存在被打断的可能性
cardinal_508 2012-03-26
  • 打赏
  • 举报
回复
传输的结构体中并不包含指针,我把计时器改成了线程正在测试
zhu_jiang 2012-03-26
  • 打赏
  • 举报
回复
直接写个while循环测试,看报错不?
while(true)
{
ConnectVideo(this.hWnd);

}
WAN 2012-03-26
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 zhu_jiang 的回复:]
timer控件有一机制,如果当前未执行完而触发了下一次,那么当前的执行代码会被销毁,
[/Quote]
Forms.Timer是依赖线程消息队列实现的,怎么可能会有这样的机制??
就是假设有吧,你说的“当前的执行代码会被销毁”是指内存被回收?那样回收的也只可能是托管内存,非托管内存是不会被GC回收的,在PInvoke结束前也不会有机会调用FreeCoTaskMem释放
我是建议如果CHANNELR结构内包含指针的话,在调用前应检查其有效性
加载更多回复(6)

111,126

社区成员

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

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

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