如何在运行时没有调试器的情况下显示异常发生的行号?

时间:2016-04-25 23:55:40

标签: delphi delphi-xe

我在运行时发生异常,这是不可重现的,因此我无法在IDE /调试器中对其进行调试。我想知道代码在哪里发生,所以我用try / except语句包围了代码,插入了一个' raise exception'测试声明显示这样的堆栈跟踪以查看它是否有效:

   on e: exception do begin
          showmessage(e.StackTrace);
    end;

但是显示的消息是空的。它为什么是空的?还有另一种方法可以知道发生异常的位置吗?使用Delphi XE。

3 个答案:

答案 0 :(得分:10)

Exception.StackTrace文档表明默认实现返回一个空字符串,并且为了使用您提供GetStackInfoStringProc过程所需的功能。它还建议使用第三方提供商的一些实现(包括免费和商业),而不是编写自己的实现。

这是该文档的摘要(简要) - 访问相关链接的文档页面:

  

默认情况下,StackTrace始终为空字符串。如果希望StackTrace包含实际值,则必须为GetStackInfoStringProc分配一个可以从堆栈信息生成字符串的过程。

     

使用Exception.StackTrace

     

为了使用StackTrace属性获取异常的堆栈跟踪,您必须使用(或实现)堆栈跟踪提供程序。有许多第三方解决方案,包括商业和免费。

     

一些堆栈跟踪提供程序是:

           

有关如何使用上述某些第三方堆栈跟踪提供程序的详细信息,请参阅以下博文:

     

答案 1 :(得分:4)

  

但是显示的消息是空的。为什么它是空的?

与Ken说,根据其文档,默认情况下不会实现StackTrace属性。您必须安装具有堆栈跟踪功能的第三方异常记录器才能挂接StackTrace属性。

  

有没有其他方法可以知道发生异常的位置?

如果没有可行的堆栈跟踪,则必须获取实际发生异常的代码指令的内存地址,然后将其与存储在生成的.map文件中的已编译可执行文件的地址列表进行比较(如果在项目选项中启用,这也是堆栈跟踪所必需的)。有了它,您可以推断出崩溃代码属于哪个函数,但不一定是确切的代码行。

如果异常是EExternal派生的异常(如EAccessViolation),则可以从EExternal.ExceptionRecord字段(仅限Windows)或{{1}获取内存地址} field(* Nix / OSX / iOS)。否则,请使用System.ExceptAddr()功能。

答案 2 :(得分:0)

另一个解决方案是使用http://blog.rangle.io/optimize-your-angular2-application-with-tree-shaking/框架,请查看文档中的.mab类。

您只需生成地图文件(通过框架转换为Syncommons)并将其与您的应用程序一起分发。

在项目文件中添加此用途:momrmotsynloguses Vcl.Forms, SynCommons, mORMot, SynLog, F_calc in 'F_calc.pas' {Form1}; {$R *.res} begin TSQLLog.Family.Level := LOG_STACKTRACE; // LOG_VERBOSE Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TForm1, Form1); Application.Run; end.

Synopse\SQLite3\Samples\11 - Exception logging\logview.dpr

将生成日志文件。 您可以使用此示例程序(在框架中)阅读它:

{{1}}