我们的一位客户报告了崩溃。在出现未处理的异常后,她看到了标准错误消息:
“应用程序产生了无法处理的异常...单击确定终止应用程序。单击取消调试应用程序。”
我使用 DebugDiag 生成此过程的转储。我现在正在看垃圾场。
!threads 在我的托管线程中向我显示了一个异常。有几个嵌套异常。这个在底部:
0:000> !pe -nested
...
Nested exception -------------------------------------------------------------
Exception object: 14015a98
Exception type: System.AccessViolationException
Message: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
InnerException: <none>
StackTrace (generated):
SP IP Function
0013E958 7B6EEF3B System_Windows_Forms_ni!System.Windows.Forms.Application+ThreadContext.OnThreadException(System.Exception)+0x8b
0013E994 7B6F7916 System_Windows_Forms_ni!System.Windows.Forms.Control.WndProcException(System.Exception)+0x16
0013E9A0 7B6FA39C System_Windows_Forms_ni!System.Windows.Forms.Control+ControlNativeWindow.OnThreadException(System.Exception)+0xc
0013E9A4 7B1C8512 System_Windows_Forms_ni!System.Windows.Forms.NativeWindow.Callback(IntPtr, Int32, IntPtr, IntPtr)+0x72
0013EC70 7B1D8D2E System_Windows_Forms_ni!System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32, Int32, Int32)+0x24e
0013ED0C 7B1D8997 System_Windows_Forms_ni!System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)+0x177
0013ED60 7B1D87E1 System_Windows_Forms_ni!System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext)+0x61
0013ED90 7B6EDE2B System_Windows_Forms_ni!System.Windows.Forms.Application.RunDialog(System.Windows.Forms.Form)+0x33
0013EDA4 7B7225AB System_Windows_Forms_ni!System.Windows.Forms.Form.ShowDialog(System.Windows.Forms.IWin32Window)+0x373
0013EE30 0DF41E76 PDILibReportProcessor!profdata.com.Library.libReportRenderCrystal.RenderToDisplay(System.Windows.Forms.IWin32Window, profdata.com.Library.libOutputSettings, profdata.com.Library.libApplicationConfig)+0xb6
0013EE4C 0DF416EB PDILibReportProcessor!profdata.com.Library.libReportProcessor.Process(System.Windows.Forms.IWin32Window)+0x153
0013EE60 07B37644 PDILibReportProcessor!profdata.com.Library.libReportProcessor.ProcessCrystalReport(System.String, System.Type, System.Data.DataSet, profdata.com.Library.libOutputSettings, profdata.com.Library.libApplicationConfig, System.Windows.Forms.IWin32Window, System.String)+0x74
0013EEA4 07B375B8 PDILibReportProcessor!profdata.com.Library.libReportProcessor.ProcessReport(System.String, System.Type, System.Data.DataSet, profdata.com.Library.libOutputSettings, profdata.com.Library.libApplicationConfig, System.Windows.Forms.IWin32Window)+0x18
0013EEB8 07B333C4 APRPTCashRequirements!profdata.com.AccountsPayable.frmAPCashRequirements.RunProcessOrReport()+0x7e4
StackTraceString: <none>
HResult: 80004003
该代码以表单的形式向用户显示了一个 Crystal Report。在显示报告时,应用程序尝试做某事并得到 System.AccessViolationException。
查看 NativeWindow.Callback 源代码,我看到了这一点:
private IntPtr Callback(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam)
{
Message m = Message.Create(hWnd, msg, wparam, lparam);
try
{
// calls WndProc or DefWndProc
}
catch (Exception exception)
{
this.OnThreadException(exception);
}
finally {...}
}
我想知道导致异常的消息、wParam 和 lParam 参数。(我还想确认我正在查看正确的异常对象。)这可能是对 UI 线程的调用,也可能是正常的 Windows 事件,在这种情况下我想知道是哪一个。
我得到了线程环境块:
0:000> !teb
TEB at 7ffdf000
ExceptionList: 00134144
StackBase: 00140000
StackLimit: 00130000
并转储堆栈内存:
0:000> !dqs 00130000 00140000
...
0013e968 00000000`00000000
0013e970 00000000`00000000
0013e978 00000000`00000000
0013e980 140ea9fc`00000000
0013e988 0013e998`0013ea44
0013e990 140c1d4c`7b6f7916
0013e998 7b6fa39c`0013ea54 <--- is NativeWindow.Callback
0013e9a0 0013ea6c`7b1c8512
0013e9a8 0013ec60`79edd757
0013e9b0 0013ec60`00000000
0013e9b8 0013ea6c`e0434f4d
0013e9c0 00000000`0013ea1c
0013e9c8 00000000`00000000
...
所以如果签名是这样的: SP IP 0013E9A4 7B1C8512 NativeWindow.Callback(IntPtr, Int32, IntPtr, IntPtr)+0x72
- 堆栈上的参数到底在哪里?
- 我如何检查它们以获取它们的值?
我仍然觉得我没有找到根本原因。我们有一个 ThreadException 处理程序。为什么不叫?是什么原因造成的System.AccessViolationException
?
请注意已!analyze -v
报告STATUS_BREAKPOINT
,因为用户在错误对话框“应用程序已生成异常...”处停止。