要使用JEDI JCL記錄捕獲和未捕獲的異常,應該安裝JEDI JCL。
然後嘗試一些代碼,就像從jcl\examples\windows\debug\framestrack\FramesTrackDemoMain.pas
採取了這種代碼:
你應該在編譯器,並在您的Delphi工程的選項鍊接器選項都完整的調試信息編譯,對於這個工作。
請注意,您不必調用LogException,它會自動調用您添加了異常通知器回調(JclAddExceptNotifier)的對象。不要忘了還叫JclRemoveExceptNotifier,當你從添加到表單或數據模塊被破壞,如下所示:
procedure TForm1.LogException(ExceptObj: TObject; ExceptAddr: Pointer; IsOS: Boolean);
var
TmpS: string;
ModInfo: TJclLocationInfo;
I: Integer;
ExceptionHandled: Boolean;
HandlerLocation: Pointer;
ExceptFrame: TJclExceptFrame;
begin
TmpS := 'Exception ' + ExceptObj.ClassName;
if ExceptObj is Exception then
TmpS := TmpS + ': ' + Exception(ExceptObj).Message;
if IsOS then
TmpS := TmpS + ' (OS Exception)';
mmLog.Lines.Add(TmpS);
ModInfo := GetLocationInfo(ExceptAddr);
mmLog.Lines.Add(Format(
' Exception occured at $%p (Module "%s", Procedure "%s", Unit "%s", Line %d)',
[ModInfo.Address,
ModInfo.UnitName,
ModInfo.ProcedureName,
ModInfo.SourceName,
ModInfo.LineNumber]));
if stExceptFrame in JclStackTrackingOptions then
begin
mmLog.Lines.Add(' Except frame-dump:');
I := 0;
ExceptionHandled := False;
while (chkShowAllFrames.Checked or not ExceptionHandled) and
(I < JclLastExceptFrameList.Count) do
begin
ExceptFrame := JclLastExceptFrameList.Items[I];
ExceptionHandled := ExceptFrame.HandlerInfo(ExceptObj, HandlerLocation);
if (ExceptFrame.FrameKind = efkFinally) or
(ExceptFrame.FrameKind = efkUnknown) or
not ExceptionHandled then
HandlerLocation := ExceptFrame.CodeLocation;
ModInfo := GetLocationInfo(HandlerLocation);
TmpS := Format(
' Frame at $%p (type: %s',
[ExceptFrame.ExcFrame,
GetEnumName(TypeInfo(TExceptFrameKind), Ord(ExceptFrame.FrameKind))]);
if ExceptionHandled then
TmpS := TmpS + ', handles exception)'
else
TmpS := TmpS + ')';
mmLog.Lines.Add(TmpS);
if ExceptionHandled then
mmLog.Lines.Add(Format(
' Handler at $%p',
[HandlerLocation]))
else
mmLog.Lines.Add(Format(
' Code at $%p',
[HandlerLocation]));
mmLog.Lines.Add(Format(
' Module "%s", Procedure "%s", Unit "%s", Line %d',
[ModInfo.UnitName,
ModInfo.ProcedureName,
ModInfo.SourceName,
ModInfo.LineNumber]));
Inc(I);
end;
end;
mmLog.Lines.Add('');
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
JclAddExceptNotifier(Form1.LogException);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
JclRemoveExceptNotifier(Form1.LogException);
end;
這是通常的初始化代碼:
initialization
JclStackTrackingOptions := JclStackTrackingOptions + [stExceptFrame];
JclStartExceptionTracking;
這裏的JCL FramesTrackExample.dproj演示運行:
你的目的,修改,增加了一行TMemo.Lines的代碼,改爲寫入磁盤上的日誌文件。如果你已經有一個日誌系統,那很好,如果沒有,那麼考慮Log4D。
您可以添加異常處理程序(如[MadExcept](http://madshi.net/madExceptDescription.htm)或我們的[開源單元](http://blog.synopse.info/post/2011/04)/14/Enhanced-logging-in-SynCommons))在運行期間檢索堆棧跟蹤。如果沒有這個堆棧跟蹤,找到根本原因是不可能的。添加日誌記錄將有助於調試服務。 – 2011-12-15 16:42:45
是的,您可以在捕捉到的異常情況下登錄堆棧軌道。從JEDI類庫獲取JclDebug,並將其添加到您的應用程序。如果您將問題編輯爲「如何從處理/捕獲的異常中獲取堆棧跟蹤並將其轉儲到跟蹤日誌」,我將很樂意發佈諸如答案。我曾多次使用該技術(跟蹤日誌+ JCL調試)來調試服務崩潰。 – 2011-12-15 17:18:08
聽起來就像你遇到了競爭條件。 你想過線程安全嗎? – whosrdaddy 2011-12-15 19:25:59