2016-04-25 35 views
4

我在運行時發生了一個異常,這是不可重現的,因此我無法在IDE /調試器中調試它。我想知道在代碼中出現這種情況,所以我周圍的代碼使用try/except語句,插入一個「引發異常」進行測試&聲明顯示這樣的堆棧跟蹤,看看它的工作原理:如何在沒有調試器的情況下在運行時發生異常的行號?

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

然而顯示的消息是空的。爲什麼它是空的?有另一種方法可以知道發生異常的位置嗎?使用Delphi XE。

回答

10

Exception.StackTrace文檔指示默認實現返回一個空字符串,並且爲了使用您需要提供GetStackInfoStringProc過程的功能。它還建議來自第三方提供商的一些實現(包括免費和商業),可以用來代替自己編寫。

下面是從一個文檔(簡介)節選 - 瀏覽文檔頁面的相關鏈接:

默認情況下,堆棧跟蹤始終是一個空字符串。如果您希望StackTrace包含實際值,則必須爲GetStackInfoStringProc指定一個可從堆棧信息生成字符串的過程。

使用Exception.StackTrace

爲了使用堆棧跟蹤屬性,以便獲得異常堆棧跟蹤,你必須使用(或執行)堆棧跟蹤提供商。有許多第三方解決方案,包括商業和免費。

一些堆棧跟蹤提供的是:

有關如何使用上述某些第三方堆棧跟蹤供應商的,請參閱以下博客文章的詳細信息:

4

但是顯示的消息是空的。爲什麼它是空的?

像Ken說的那樣,StackTrace屬性在默認情況下並未按照其文檔實現。您必須安裝具有堆棧跟蹤功能的第三方異常記錄器來掛接StackTrace屬性。

是否有另一種方法來知道發生異常?

沒有一個可行的堆棧跟蹤,你就必須獲得該代碼指令,其中異常實際發生的內存地址,然後將其與存儲在生成.map文件爲您編譯的可執行文件的地址的列表(如果在項目選項中啓用,這也是堆棧跟蹤所必需的)。由此,您可以推斷崩潰代碼屬於哪種功能,但不一定是代碼的確切代碼。

如果異常是EExternal衍生除外(例如EAccessViolation),你可以從EExternal.ExceptionRecord領域內存地址(僅適用於Windows),或EExternal.ExceptionAddress場(* NIX/OSX/iOS版)。否則,請使用System.ExceptAddr()函數。

0

另一種解決方案是使用synopse框架,請看文檔中的TSQLLog類。

您只需生成地圖文件(由框架轉換爲.mab)並將其與您的應用程序分發。

將此項用於您的項目文件:Syncommons,momrmotsynlog

uses 
    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 
相關問題