11

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 が例外をキャッチするのを止めて、アプリケーションが werfault クラッシュを許可されるようにするにはどうすればよいですか。これにより、問題の原因となっている命令を取得できます。これは浮動小数点の例外です。ゼロで除算しようとしているコードがどこかにあります。


他の誰かが同じ状況で同じクラッシュを起こしています:

サードパーティのアドオンをすべて無効にし、IE をセーフ モードで実行してみるという Microsoft からの有益な提案を受けて。

この問題を経験しているのは私だけではないことを証明できてうれしいです。私は解決策にもっと興味があります。


命令で浮動小数点制御ワードを操作することにより、浮動小数点ユニットに例外を発生させないように要求することにより、例外をマスクできます。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)
    }

それでも、例外をスローしているを見つける方法を知りたいです。

4

2 に答える 2

5

例外をスローするコード行を取得するには、Microsoft にmshtml.dllのソースを問い合わせる必要があります。ここで、アドレス 00378B89 の命令によって例外がスローされます。

CPU ウィンドウを開いて DLL からのマシン コードを調べてみることもできますが、他の人のマシン コードをデバッグすることにまだ慣れていない場合は、それがどれほど役立つかわかりません。

デバッガーのスタック トレースと JCL スタック トレースは、かなり似ています。主な違いは、JCL は DLL 関数に関する情報を提供しようとしますが、デバッガーは提供しないことです。ただし、それほど大きな違いはありません。JCL が検出する最も近い関数名は、実際の障害のある命令からほぼ 1 メガバイト離れているため、JCL が表示する情報は無意味です。もう 1 つの違いは、TWinControl.MainWndProc がスタック トレースに含まれているかどうかです。これは、スタック トレースが DCU デバッグ情報を読み取ることによって決定されたのか、スタックの物理的な内容を分析することによって決定されたのかによると思われます。

于 2012-02-27T23:07:56.493 に答える