Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 如何在Internet Explorer中调试零除异常?_Delphi_Internet Explorer 9_Delphi 5_Twebbrowser - Fatal编程技术网

Delphi 如何在Internet Explorer中调试零除异常?

Delphi 如何在Internet Explorer中调试零除异常?,delphi,internet-explorer-9,delphi-5,twebbrowser,Delphi,Internet Explorer 9,Delphi 5,Twebbrowser,我正在Windows应用程序中托管Internet Explorer。我可以向下滚动到文档的底部。然后,当我尝试向上滚动时,我得到一个除零异常: 当我使用Page Up滚动时,崩溃似乎发生在调用 - 当我使用鼠标滚动时,崩溃发生在调用 不管怎样,崩溃都发生在Internet Explorer中 异常发生时Delphi显示的堆栈跟踪: 与绝地的异常跟踪显示的堆栈跟踪不同: Exception EZeroDivide in module mshtml.dll at 00378B89. Fl

我正在Windows应用程序中托管Internet Explorer。我可以向下滚动到文档的底部。然后,当我尝试向上滚动时,我得到一个除零异常:

当我使用Page Up滚动时,崩溃似乎发生在调用 -

当我使用鼠标滚动时,崩溃发生在调用

不管怎样,崩溃都发生在Internet Explorer中

异常发生时Delphi显示的堆栈跟踪

与绝地的异常跟踪显示的堆栈跟踪不同:

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捕获异常,从而允许应用程序崩溃,从而获得导致问题的指令。这是一个浮点异常,某处是试图被零除的代码


其他人在同样的情况下也会遇到同样的崩溃:

微软建议他关闭任何第三方插件,并尝试在安全模式下运行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)
    }

不过,我还是想知道如何找到引发异常的

要获取引发异常的代码行,您必须向Microsoft索取mshtml.dll的源代码。这就是地址00378B89处的指令引发异常的地方

您可以尝试打开CPU窗口并查看DLL中的机器代码,但是如果您还不习惯调试其他人的机器代码,我不知道这对您有多大好处


调试器的堆栈跟踪和JCL堆栈跟踪看起来与我非常相似。主要区别在于JCL试图提供一些关于DLL函数的信息,而调试器没有。不过,这没什么区别;JCL显示的信息毫无意义,因为它找到的最接近的函数名距离实际的故障指令几乎有一兆字节。另一个区别是TWinControl.MainWndProc是否包含在堆栈跟踪中,我怀疑这是由于堆栈跟踪是通过读取DCU调试信息还是通过分析堆栈的物理内容来确定的。

如果不使用
Math.setExceptionTask([exInvalidOp,exDenormalized,exZeroDivide,exOverflow,exUnderflow,exPrecision])
,您会发现该修复程序仅适用于64位Windows

我认为这仅仅是一个经典问题:您必须设置控制字(Set8087CW).@AndreasRejbrand这是所有应用程序都应该始终打开的东西吗?还是只应该打开和关闭以屏蔽我得到的异常?(即,如果我只打开它来隐藏此表单上的异常,我不知道还有多少不是我的代码仍将崩溃)如果这是每个程序都应该始终打开的东西,那么为什么默认情况下它会关闭?归根结底,这是因为MS习惯性地在编译代码时屏蔽了FP异常。Embarcadero工具习惯性地解除了它们的屏蔽。因此,编写MS代码时假设不会引发FP异常,并且对它们没有弹性在调用MS代码之前,您必须屏蔽异常。如果您的应用程序没有浮点值,则只需在启动时屏蔽异常,并完成处理。调用
Set8087CW($027F)
在启动时,您就可以开始了。这是您的解决方案。它在英特尔处理器文档中有说明。需要进行大量的位旋转。不太不透明的方法是调用
Math.SetExceptionMask([exInvalidOp,exDenormalized,exZeroDivide,exOverflow,exUnderflow,exPrecision]))
。当然,我敢打赌这是在D6中引入的,我想您的项目仍然处于良好的D5状态!“不过,我想知道如何找到引发异常的行。”那是毫无意义的。当你得到这些信息时,你会怎么做。那段代码是在假设FP异常被屏蔽的情况下编写的。那段代码,引发异常的代码是正确的。它完全按照设计工作。它不是你的代码,你也无法更改它。你所能做的就是向它提供它所需要的CWnts。我希望找出如何使Delphi的调试器停止在引发异常的代码行(cpu窗口;汇编代码行)上。我有Microsoft Symbol server和一个可以查询它的调试器(WinDbg)。但由于某种原因,直到异常返回到我自己的模块中,才“看到”它(也许这是一个COM安全调用互操作的东西-但是这将是一个
EOleSysError
,而不是
EZeroDivide
。我想我能得到的最好方法是自己加载
DbgHelp.dll
,然后调用导出,获取偏移量
00378B89
的符号信息。如果我开始编写DbgHelp导入,我将发布我的结果。这个问题是针对Delphi5的,所以这是没有意义的。我猜你的意思是只在32位上工作,而不是在64位上。