如何找到非托管异常的来源?

时间:2010-12-05 12:00:03

标签: winforms native-methods

我有一个WinForms应用程序,我希望能够提供HTML编辑功能。所以我已经将Lutz Roeder's HTML Writer从C#翻译成VB.NET,并将其从Windows窗体转换为自定义用户控件,现在以MDI子窗体形式托管。

一切正常,直到我关闭父MDI,在这种情况下崩溃,我无法捕获异常。

我已将编辑器控件隔离到一个小的vanilla WinForms应用程序中,该应用程序没有做任何其他事情,并验证问题仍然存在。

我还打开了非托管代码调试(我正在使用VS2010,编译x86和Framework 3.5),我得到的就是:

Windows has triggered a breakpoint in HtmlEditorMdi.exe.
This may be due to a corruption of the heap, which indicates a bug in HtmlEditorMdi.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while HtmlEditorMdi.exe has focus.
The output window may have more diagnostic information.

我注意到的另一件事是,如果我在打开包含编辑器的表单后离开很长的间隔,它就不会崩溃。

我真正欣赏的是关于如何寻找这个问题的一些想法。当然,我在C#转换为VB时犯了一个错误,但我很难知道在哪里看。

修改

我运行了附带调试器的应用程序,并没有给我任何有用的东西。

我得到的只是Windows'应用程序已停止工作'消息,问题详细信息中包含此信息:

Problem signature:
  Problem Event Name:   APPCRASH
  Application Name: HtmlEditorMdi.exe
  Application Version:  1.0.0.0
  Application Timestamp:    4cfb74c7
  Fault Module Name:    mscorwks.dll
  Fault Module Version: 2.0.50727.4952
  Fault Module Timestamp:   4bebd49a
  Exception Code:   c0000005
  Exception Offset: 000022b5
  OS Version:   6.1.7600.2.0.0.256.1
  Locale ID:    2057
  Additional Information 1: 0a9e
  Additional Information 2: 0a9e372d3b4ad19135b953a78882e789
  Additional Information 3: 0a9e
  Additional Information 4: 0a9e372d3b4ad19135b953a78882e789

我可以看到它是一种访问冲突,但即使我去了 Debug>例外> Win32 Exceptions ,并勾选 c0000005 ,当它中断时我没有得到任何有用的东西 - 只是'没有可用的来源'。

2 个答案:

答案 0 :(得分:1)

您引用的第一条消息是由Windows堆管理器在发现内部堆结构被销毁时生成的。它会在看到附加调试器时显示该诊断信息。第二个引用的块是当它绕过诊断(没有附带调试器)时发生的事情,当它试图在损坏的堆中释放内存时,它会在硬件异常上发生爆炸。

堆损坏的问题在于,在生成诊断之前很长时间才会发生真正的损坏。您可以在“调用堆栈”窗口中看到导致诊断的堆栈跟踪,您需要启用Microsoft符号服务器以获取Windows功能的有意义的符号。但它不会告诉你任何真正造成损害的代码有用,这需要一台时间机器。

这种堆损坏总是由非托管代码引起的。 AccessViolation异常是众所周知的C / C ++程序员的祸害,也是托管代码变得流行的一个重要原因。虽然Lutz的源代码都是托管的,但它包含P / Invoke和COM接口声明的 lot 。没有好的方法来调试它们,你没有源代码。

当你将它们转换为VB.NET时,将其中一个声明巧妙地弄错了肯定是这种情况发生的一种方式。它也可能是那个虫子总是在那里,但刚刚养成它丑陋的脑袋。幸运的你。顺便说一句,我不认为代码是64位清理,强制它在32模式下运行,以便快速修复。对于主要的EXE项目:Project + Properties,Compile选项卡,向下滚动,Advanced Compile Options,Target CPU = x86。这仅在您运行64位版本的Windows时才有意义。

除此之外,我建议您按原样使用C#项目。在.NET中,混合语言是一种非常受支持的方案。

答案 1 :(得分:0)

windbg调试器是这类问题的“大枪”。它可以经常通过告诉你有关处理异常等的方式给你提供线索。唯一的问题是它不易使用并且具有很高的学习曲线。