Delphi异常后获取堆栈跟踪

Delphi异常后获取堆栈跟踪

本文介绍了Delphi异常后获取堆栈跟踪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to figure out how to obtain a stack trace after an exception is thrown in Delphi. However, when I try to read the stack in the Application.OnException event using the function below, the stack already seems to be flushed and replaced by the throwing procedures.

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调用之前(之后也可以)的内容。

That's obviously not what I'm looking for, although it's correct. I'd like to retrieve the stack as it was just before the exception was thrown, or in other words the contents before (after would do too) the OnException call.

有什么办法吗?

我知道我正在重新发明轮子,因为madExcept / Eurekalog / jclDebug已经做到了,但是我想知道它是怎么做到的。

I am aware that I'm reinventing the wheel, because the folks over at madExcept/Eurekalog/jclDebug have already done this, but I'd like to know how it's done.

推荐答案

不可能手动获取 OnException 事件内部的可行堆栈跟踪。正如您已经注意到的那样,错误发生时的堆栈在触发事件时已经消失了。您要查找的内容需要在引发异常时获取堆栈跟踪。第三方异常记录器,例如MadExcept,EurekaLog等,可以通过将RTL自身内部的关键函数和核心异常处理程序挂钩来为您处理这些细节。

It is not possible to manually obtain a viable stack trace from inside the OnException event. As you have already noticed, the stack at the time of the error is already gone by the time that event is triggered. What you are looking for requires obtaining the stack trace at the time the exception is raised. Third-party exception loggers, like MadExcept, EurekaLog, etc handle those details for you by hooking into key functions and core exception handlers inside of the RTL itself.

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

In recent Delphi versions, the SysUtils.Exception class does have public StackTrace and StackInfo properties now, which would be useful in the OnException event except for the fact that Embarcadero has chosen NOT to implement those properties natively for unknown reasons. It requires third-party exception loggers to assign handlers to various callbacks exposed by the Exception class to generate stack trace data for the properties. But if you have JclDebug installed, for instance, then you could provide your own callback handlers in your own code that use JCL's stack tracing functions to generate the stack data for the properties.

这篇关于Delphi异常后获取堆栈跟踪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 20:01