Hug*_*une 3 c# debugging exception visual-studio-2008 winforms
我有一个旧的Windows.Forms应用程序,我正在尝试调试.
有时在运行几分钟后,它将产生ArithmeticException或OverflowException.源必须位于代码库中的某个位置,但堆栈跟踪始终指向该行Application.Run(mainForm);
StackTrace没用,因为它只显示Windows.Forms本机调用:
bei System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
bei System.Windows.Forms.Application.Run(Form mainForm)
bei Program.Main() in C:\xy\Program.cs:Zeile 102.
Run Code Online (Sandbox Code Playgroud)
为了找到我增加了一个异常处理程序异常的来源
System.Windows.Forms.Application.ThreadException和System.AppDomain.CurrentDomain.UnhandledException.
我尝试过启用和禁用捕获异常
System.Windows.Forms.Application.SetUnhandledExceptionMode();
永远不会调用ThreadException事件处理程序.UnhandledException事件处理程序只报告我在Visual Studio中看到的相同异常.
在Visual Studio中,我在抛出异常时启用了中断执行:
这没有任何影响.
我该怎么做才能找到有问题的代码行?
编辑:完整的异常详细信息:

如果我在没有附加任何调试器的情况下启动进程,并在连接调试器之前等待它崩溃,我会得到以下异常:
Unbehandelte Ausnahme bei 0x0c9f9e1b in program.exe: 0xC0000090: Floating-point invalid operation.
Run Code Online (Sandbox Code Playgroud)
调试然后导致这个反汇编
0C9F9E12 add esi,10h
0C9F9E15 push 0CA1FD48h
0C9F9E1A push eax
0C9F9E1B fmul qword ptr ds:[0CA202E0h]
0C9F9E21 fstp dword ptr [esp+18h]
Run Code Online (Sandbox Code Playgroud)
我无法解析这个,但我怀疑这只是DispatchMessageW函数
这里的诊断是您在进程中有遗留的非托管代码,从您发布的调用堆栈判断可能是旧的ActiveX控件.
这些例外是FPU(浮点处理器)生成的硬件异常.可以通过引发异常来报告问题的操作模式,例如您看到的STATUS_FLOAT_OVERFLOW和STATUS_FLOAT_INVALID_OPERATION异常.而不是生成无穷大,NaN或非正规.FMUL指令很容易产生这样的异常.
更改FPU操作模式的软件与托管代码基本上不兼容.这要求FPU异常始终被屏蔽.掩盖这些异常是完全正常的,所有现代软件都可以完成.早在上个世纪,这些例外被认为是诊断浮点计算失败的一项资产.特别是,旧的Borland运行时库揭示了这些异常.
好吧,如果您还没有收到该消息,这都是相当糟糕的消息.首先要看的是尝试诊断此代码抛出浮点异常的原因.不良数据往往是最常见的原因.其次,你真的有被改变做点什么FPU控制寄存器,这很容易导致托管代码失败也是如此.特别是WPF代码中的问题,它喜欢使用NaN.
使用调试器很容易找到这样的代码.使用Debug + Windows + Registers调试器窗口.右键单击窗口并勾选"浮点"选项.CTRL寄存器的值至关重要,它应该027F在托管程序中.逐步完成程序,粗略的是,当寄存器发生变化时,你找到了麻烦制造者.如果它是64位程序,那么也勾选"SSE",MXCSR寄存器应该是00001F80.
您无法使用托管代码直接重置FPU控制寄存器,但您可以使用技巧.只要处理异常,CLR就会重置它.因此,在导致控制寄存器值更改的语句之后,可能的修复是故意抛出并捕获异常:
try { throw new Exception("Resetting FPU control register, please ignore"); }
catch { }
Run Code Online (Sandbox Code Playgroud)
在msvcrt.dll中对_controlfp()函数进行设置是一种更直接的方法.但是当然,由于两者的副作用现在该库正在以不是为其设计的模式运行,它当然不会期望遇到Nan和Infinity值.从长远来看,您确实需要考虑退出旧组件或库.
| 归档时间: |
|
| 查看次数: |
4972 次 |
| 最近记录: |