Delphi在异常后获取堆栈跟踪

标签 delphi exception stack-trace

我试图弄清楚如何在 Delphi 中抛出异常后获取堆栈跟踪。但是,当我尝试使用下面的函数读取 Application.OnException 事件中的堆栈时,堆栈似乎已经被刷新并被抛出过程替换。

function GetStackReport: AnsiString;
var
    retaddr, walker: ^pointer;
begin

    // ...

    // History of stack, ignore esp frame
    asm
        mov walker, ebp
    end;

    // assume return address is present above ebp
    while Cardinal(walker^) <> 0 do begin
        retaddr := walker;
        Inc(retaddr);
        result := result + AddressInfo(Cardinal(retaddr^));
        walker := walker^;
    end;
end;

这是我得到的结果:

001A63E3: TApplication.HandleException (Forms)
00129072: StdWndProc (Classes)
001A60B0: TApplication.ProcessMessage (Forms)

这显然不是我想要的,尽管它是正确的。我想检索抛出异常之前的堆栈,或者换句话说,在 OnException 调用之前(之后也可以)的内容。

有什么办法可以做到这一点吗?

我知道我正在重新发明轮子,因为 madExcept/Eurekalog/jclDebug 的人们已经做到了这一点,但我想知道它是如何完成的。

最佳答案

无法从 OnException 事件内部手动获取可行的堆栈跟踪。正如您已经注意到的,当事件被触发时,错误发生时的堆栈已经消失了。您要查找的内容需要获取引发异常时的堆栈跟踪。第三方异常记录器(例如 MadExcept、EurekaLog 等)通过 Hook RTL 本身内部的关键函数和核心异常处理程序来为您处理这些详细信息。

在最近的 Delphi 版本中,SysUtils.Exception 类现在确实具有公共(public) StackTraceStackInfo 属性,这在OnException 事件,但 Embarcadero 由于未知原因选择不在 native 实现这些属性。它需要第三方异常记录器将处理程序分配给 Exception 类公开的各种回调,以生成属性的堆栈跟踪数据。但是,例如,如果您安装了 JclDebug,那么您可以在自己的代码中提供自己的回调处理程序,使用 JCL 的堆栈跟踪函数来生成属性的堆栈数据。

关于Delphi在异常后获取堆栈跟踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15890029/

相关文章:

java - Jar 文件初始化程序异常

java - 如何找出线程卡住的原因?

android - 如何设置 llvm-symbolizer?

delphi - 在 Firemonkey 中使用 JPG

delphi - 我可以从 IDE 内部运行 Delphi EXE 而无需重新编译吗?

java - PBKDF2WithHmacSHA512 SecretKeyFactory 不可用

c# - 捕获所有内部异常详细信息的最佳做法是什么?

Haskell HasCallStack 意外行为

Delphi类的动态数组

Delphi 匿名函数传递给内联函数