我在Windows应用程序中托管Internet Explorer。我可以向下滚动到文档的底部。当我然后尝试向上滚动时,我得到除以零异常:
当我使用 Page Up 滚动时,似乎在调用时发生了崩溃
- IOleInPlaceActiveObject:TranslateAccelerator
当我使用鼠标滚动时,在调用
期间发生了崩溃无论哪种方式,崩溃都发生在Internet Explorer中。
Delphi在异常时显示的堆栈跟踪:
与Jedi异常跟踪显示的堆栈跟踪不同:
Exception EZeroDivide in module mshtml.dll at 00378B89.
Floating point division by zero.
Exception raised by object: TEmbeddedWB
Full Exception Details:
EZeroDivide
ExceptionCode: 0xC000008E (EXCEPTION_FLT_DIVIDE_BY_ZERO)
The thread tried to divide a floating-point value by a floating-point divisor of zero.
ExceptionFlags: 0x00000002
ExceptionAddress: 0x574C8B89
Parameters: (0x00000000)
EXCEPTION_RECORD: nil
Message: Floating point division by zero
Stack Trace:
[574C8B89] Unknown function at DllGetClassObject + $FF033
[004CA61E] OleCtrls.TOleControl.WndProc (Line 2171, "olectrls.pas" + 12) + $10
[006CF62A] EmbeddedWB.TEmbeddedWB.WBWndProc (Line 1492, "EmbeddedWB.pas" + 31) + $8
[0046200C] Forms.StdWndProc (Line 1459, "Forms.pas" + 8) + $0
[0046D2A2] Forms.TApplication.IsKeyMsg (Line 6588, "Forms.pas" + 20) + $1E
[0046D43F] Forms.TApplication.ProcessMessage (Line 6626, "Forms.pas" + 9) + $2A
[0046D4AB] Forms.TApplication.HandleMessage (Line 6649, "Forms.pas" + 1) + $6
[0046938C] Forms.TCustomForm.ShowModal (Line 4692, "Forms.pas" + 22) + $5
[007D72AD] FMain.TfrmMain.actControlPanelExecute (Line 566, "FMain.pas" + 5) + $5
[00424AF5] Classes.TBasicAction.Execute (Line 8077, "Classes.pas" + 3) + $9
[00455369] ActnList.TContainedAction.Execute + $31
[0045B6AE] Menus.TMenuItem.Click (Line 1738, "Menus.pas" + 9) + $8
[0045CD71] Menus.TMenu.DispatchCommand (Line 2446, "Menus.pas" + 5) + $5
我尝试在WinDbg中调试崩溃:
ModLoad: 00000000`75360000 00000000`75372000 C:\Windows\syswow64\DEVOBJ.dll
ModLoad: 00000000`71940000 00000000`719fa000 C:\Windows\SysWOW64\d2d1.dll
ModLoad: 00000000`715e0000 00000000`716ea000 C:\Windows\SysWOW64\DWrite.dll
ModLoad: 00000000`71870000 00000000`718f3000 C:\Windows\SysWOW64\dxgi.dll
ModLoad: 00000000`74fb0000 00000000`74fdd000 C:\Windows\syswow64\WINTRUST.dll
ModLoad: 00000000`71db0000 00000000`71ddc000 C:\Windows\SysWOW64\d3d10_1.dll
ModLoad: 00000000`71900000 00000000`7193a000 C:\Windows\SysWOW64\d3d10_1core.dll
ModLoad: 00000000`6e5c0000 00000000`6e6ec000 C:\Windows\SysWOW64\D3D10Warp.dll
ModLoad: 00000000`6d480000 00000000`6d63b000 C:\Windows\SysWOW64\jscript9.dll
ModLoad: 00000000`714f0000 00000000`714fb000 C:\Windows\SysWOW64\msimtf.dll
ModLoad: 00000000`6f080000 00000000`6f0ab000 C:\Windows\SysWOW64\msls31.dll
ModLoad: 00000000`082c0000 00000000`082fc000 C:\Windows\SysWOW64\Oleacc.dll
ModLoad: 00000000`613e0000 00000000`6140e000 C:\Windows\SysWOW64\MLANG.dll
ModLoad: 00000000`62bb0000 00000000`62cb2000 C:\Windows\SysWOW64\d3d10.dll
ModLoad: 00000000`62b70000 00000000`62ba3000 C:\Windows\SysWOW64\d3d10core.dll
(834.d04): Unknown exception - code c000008e (first chance)
但是因为Delphi捕获了所有异常,所以它永远不会泄漏并打破WinDbg。 (或许这就是为什么WinDbg不会破坏)。
如何阻止Delphi捕获异常,以便允许应用程序崩溃,因此我可以获得导致问题的指令。这是一个浮点异常, 某处 是试图除以零的代码。
在同样的情况下,其他人也遭遇了同样的崩溃:
根据Microsoft的有用建议,他关闭了任何第三方插件,并尝试在安全模式下运行IE。
虽然很难被证明是我不是唯一遇到这个问题的人;我对解决方案更感兴趣。
通过使用FLDCW
指令浮动浮点控制字,通过要求浮点单元不引发异常,可以屏蔽 <:>
procedure TfrmControlPanel.FormCreate(Sender: TObject);
begin
FSaved8087CW := Default8087CW; // Save this because Set8087CW changes it.
Set8087CW($027F); //restore later using Set8087CW(FSaved8087CW);
//$027F comes from http://msdn.microsoft.com/en-us/library/ms235300.aspx
{
Scrolling in browser was causing floating point exceptions
http://stackoverflow.com/questions/9472265/how-to-debug-division-by-zero-exception-in-internet-explorer
What it boils down to is that MS habitually compile their code with FP exceptions masked.
Embarcadero tools habitually unmask them. Thus the MS code is written assuming that FP exceptions
will not be raised and is not resilient to them. To deal with that you have to mask the exceptions
before calling into the MS code. If your app does not floating point then just mask the exceptions
at start up and be done with it. Call Set8087CW($027F) at start up and you are good to go.
Default8087CW: $1332 = 0001 0011 0011 0010
New 8087CW: $027F = 0000 0010 0111 1111
...I RCPC ..MM MMMM
Bit 0: Invalid Operation (IM) |
Bit 1: Denormal Operand (DM) |
Bit 2: Zero Divide (ZM) | Exception Masks (Bits 0..5)
Bit 3: Overflow (OM) | When one of these mask bits is set, its corresponding x87 FPU
Bit 4: Underflow (UM) | floating-point exception is blocked from being generated
Bit 5: Precision (PM) |
Bit 6: (reserved)
Bit 7: (reserved)
Bit 8: +Precision Control (PC) 00=Single Precision (24 bits), 10=Double Precision (53 bits), 11=Double Extended Precision (64 bits), 01=reserved
Bit 9: /
Bit 10: + Rounding Control (RC)
Bit 11: /
Bit 12: Infinity Control | not meaningful for anything past the 80287 math coprocessor
Bit 13: (reserved)
Bit 14: (reserved)
Bit 15: (reserved)
}
不过,我想知道如何找到抛出异常的 行 。
答案 0 :(得分:5)
要获取引发异常的代码行,您必须要求Microsoft提供 mshtml.dll 的源代码。这是通过地址00378B89处的指令抛出异常的地方。
您可以尝试打开CPU窗口并查看DLL中的机器代码,但如果您还不习惯调试其他人的机器代码,我不知道它对您有多大帮助。
调试器的堆栈跟踪和JCL堆栈跟踪看起来与我非常相似。主要区别在于JCL尝试提供有关DLL函数的一些信息,而调试器则没有。但这没什么区别; JCL显示的信息毫无意义,因为它找到的最近的函数名称距离实际的错误指令几乎是一兆字节。另一个区别是TWinControl.MainWndProc是否包含在堆栈跟踪中,我怀疑这是由于堆栈跟踪是通过读取DCU调试信息还是通过分析堆栈的物理内容来确定的。
答案 1 :(得分:0)
如果您不使用Math.SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide, exOverflow, exUnderflow, exPrecision])
,则会发现此修复程序仅适用于 64位Windows 。