无法捕获的 AccessViolationException
我快要绝望了。我正在使用 C# 和相当多的 p/Invoking 为 Windows Mobile 6.1 开发一个现场服务应用程序。 (我想我引用了大约 50 个本机函数)
在正常情况下,这没有任何问题,但是当我开始强调 GC 时,我遇到了令人讨厌的 0xC0000005 错误,女巫似乎无法捕获。在我的测试中,我快速关闭并打开一个对话框表单(该表单确实使用了本机函数,但为了测试我将它们注释掉了),过了一会儿,Windows Mobile 错误报告器出现告诉我有一个致命的错误我的应用程序中出现错误。
我的代码在 Application.Run(masterForm);
周围使用了 try-catch 并挂钩到 CurrentDomain.UnhandledException
事件,但应用程序仍然崩溃。即使我附加调试器,当异常发生时,Visual Studio 也只是告诉我“与设备的远程连接已丢失”。
由于我没有成功在托管环境中捕获异常,所以我试图弄清楚错误报告器日志文件。但这没有任何意义,关于错误的唯一一致的是它发生的应用程序。
应用程序发生的线程对我来说是未知的,发生错误的模块有时会有所不同(我'我见过我的application.exe、WS2.dll、netcfagl3_5.dll和mscoree3_5.dll),甚至错误代码也不总是相同的。 (大多数时候是 0xC0000005,但我也看到过 0X80000002 错误,这是对第一个字节的警告?)
我尝试通过 bugtrap 进行调试,但奇怪的是,它崩溃了,并显示相同的错误代码 (0xC0000005)。我尝试使用 Visual Studio 打开 kdmp 文件,但我似乎对此没有任何意义,因为它只在我进入错误时显示反汇编代码(除非我有正确的 .pbb 文件,而我没有't)。 WinDbg 也是如此。
长话短说:坦率地说,我不知道在哪里寻找这个错误,我希望 stackoverflow 上的一些聪明的人能知道。我很高兴提供一些代码,但目前我不知道要提供哪一部分。
非常感谢任何帮助!
[2010 年 5 月 3 日编辑]
正如您在我对 Hans 的评论中所看到的,在取消所有 P/Invoke 的注释后,我重新测试了整个程序,但这并没有解决我的问题。我尝试用尽可能少的代码重现错误,最终看起来多线程访问是给我带来所有问题的原因。
在我的应用程序中,我有一个用户控件,用作手指/轻弹滚动列表。在此控件中,我为列表中的每个项目使用位图作为画布。在这个画布上绘图是由一个单独的线程处理的,当我禁用这个线程时,错误似乎消失了。我将对此进行更多测试,并将结果发布在这里。
I'm getting close to desperate.. I am developing a field service application for Windows Mobile 6.1 using C# and quite some p/Invoking. (I think I'm referencing about 50 native functions)
On normal circumstances this goes without any problem, but when i start stressing the GC i'm getting a nasty 0xC0000005 error witch seems uncatchable. In my test i'm rapidly closing and opening a dialog form (the form did make use of native functions, but for testing i commented these out) and after a while the Windows Mobile error reporter comes around to tell me that there was an fatal error in my application.
My code uses a try-catch around the Application.Run(masterForm);
and hooks into the CurrentDomain.UnhandledException
event, but the application still crashes. Even when i attach the debugger, visual studio just tells me "The remote connection to the device has been lost" when the exception occurs..
Since I didn't succeed to catch the exception in the managed environment, I tried to make sense out of the Error Reporter log file. But this doesn't make any sense, the only consistent this about the error is the application where it occurs in.
The thread where the application occurs in is unknown to me, the module where the error occurs differs from time to time (I've seen my application.exe, WS2.dll, netcfagl3_5.dll and mscoree3_5.dll), even the error code is not always the same. (most of the time it's 0xC0000005, but i've also seen an 0X80000002 error, which is a warning accounting the first byte?)
I tried debugging through bugtrap, but strangely enough this crashes with the same error code (0xC0000005). I tried to open the kdmp file with visual studio, but i can't seem to make any sense out of this because it only shows me disassembler code when i step into the error (unless i have the right .pbb files, which i don't). Same goes for WinDbg.
To make a long story short: I frankly don't have a single clue where to look for this error, and I'm hoping some bright soul on stackoverflow does. I'm happy to provide some code but at this moment I don't know which piece to provide..
Any help is greatly appreciated!
[EDIT May 3rd 2010]
As you can see in my comment to Hans I retested the whole program after I uncommented all P/Invokes, but that did not solve my problem. I tried reproducing the error with as little code as possible and eventually it looks like multi-threaded access is the one giving me all the problems.
In my application I have a usercontrol that functions as a finger / flick scroll list. In this control I use a bitmap for each item in the list as a canvas. Drawing on this canvas is handled by a separate thread and when i disable this thread, the error seems to disappear.. I'll do some more tests on this and will post the results here.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
捕获此异常不是一种选择。这是线程可能遭受的最严重的心脏病发作,CPU 检测到严重问题并且无法继续运行代码。这总是由行为不当的非托管代码引起的,听起来您的程序中运行了大量非托管代码。您需要集中精力调试非托管代码以达到目的。
AV 的两个最常见原因是
堆栈损坏。最常见的原因是堆栈上分配的数组边界溢出。这可能会覆盖堆栈上其他变量的值或破坏函数返回地址。诊断起来更容易一些,它往往可以很好地重复并且具有立竿见影的效果。一个副作用是调试器在损坏发生后立即失去显示调用堆栈的能力。
堆损坏是最可能发生的一种情况,也是最严重的一种情况。最典型的解决方法是使用监视堆完整性的调试分配器调试调试版本中的代码。
标头提供了一个。这不是一个有保证的方法,你可能会遇到一些非常讨厌的 Heisenbug,它们只会在发布版本中出现。除了仔细的代码审查之外,可用的选项很少。祝你好运,你会需要它。Catching this exception is not an option. It is the worst kind of heart attack a thread can suffer, the CPU has detected a serious problem and cannot continue running code. This is invariably caused by misbehaving unmanaged code, it sounds like you've got plenty of it running in your program. You need to focus on debugging that unmanaged code to get somewhere.
The two most common causes of an AV are
Heap corruption. The unmanaged code has written data to the heap improperly, destroying the structural integrity of the heap. Typically caused by overflowing the boundary of an allocated block of memory. Or using a heap block after it was freed. Very hard to diagnose, the exception will be raised long after the damage was done.
Stack corruption. Most typically caused by overflowing the boundaries of an array that was allocated on the stack. This can overwrite the values of other variables on the stack or destroy the function return address. A bit easier to diagnose, it tends to repeat well and has an immediate effect. One side-effect is that the debugger loses its ability to display the call stack right after the damage was done.
Heap corruption is the likely one and the hard one. This is most typically tackled by debugging the code in the debug build with a debug allocator that watches the integrity of the heap. The
<crtdbg.h>
header provides one. It's not a guaranteed approach, you can have some really nasty Heisenbugs that only rear their head in the Release build. Very few options available then, other than careful code review. Good luck, you'll need it.原来是Interlocked引起的异常。
在我的代码中,有一个整数
_drawThreadIsRunning
,当绘制线程运行时,该整数设置为 1,否则设置为 0。我使用 Interlocked 设置此值:if (Interlocked.Exchange(ref _drawThreadIsRunning, 1) == 0) { /* run thread */ }
当我更改此行时,整个事情都有效,所以看起来某处存在线程安全问题,但我无法弄清楚。 (即,我不想浪费更多时间来弄清楚)
感谢大家的帮助!
It turns out to be an exception caused by Interlocked.
In my code there is an integer
_drawThreadIsRunning
which is set to 1 when the draw-thread is running, and set to 0 otherwise. I set this value using Interlocked:if (Interlocked.Exchange(ref _drawThreadIsRunning, 1) == 0) { /* run thread */ }
When i change this line the whole thing works, so it seems that there is a problem with threadsafety somewhere, but i can't figure it out. (ie. i don't want to waste more time figuring it out)
Thanks for the help guys!