2009-08-19 24 views

答えて

27

JCLは無料で、そのための機能を持っています。これは、スタックトレースがどれくらいうまくできているか、どのくらいのデバッグ情報があるかによって異なります。

JclDebug.pas

function FileByLevel(const Level: Integer = 0): string; 
function ModuleByLevel(const Level: Integer = 0): string; 
function ProcByLevel(const Level: Integer = 0): string; 
function LineByLevel(const Level: Integer = 0): Integer; 
+14

これを追加すると、何らかの種類のデバッグ情報なしにはできません。 –

6

our TSynMapFile class参照してください。

.mapファイルをロードし、最適化されたバイナリ形式に圧縮することができます。 .mapよりもはるかに小さくなります(例:900 KB .map - > 70 KB .mab)。この.mabはexe内に簡単に埋め込むことができます。したがって、JCLまたはMadExceptで使用される形式よりも小さく、Delphiによってコンパイル時に埋め込まれた情報よりも小さくなります。ここでは、例えば

Map := TSynMapFile.Create; // or specify an exe name 
try 
    i := Map.FindSymbol(SymbolAddr); 
    if i>=0 then 
    writeln(Map.Symbols[i].Name); 
    // or for your point: 
    writeln(Map.FindLocation(Addr)); // e.g. 'SynSelfTests.TestPeopleProc (784)' 
finally 
    Map.Free; 
end; 

それが私たちのロギングクラスから使用されている方法です。

あなたはそのように使用します。

procedure TSynLog.Log(Level: TSynLogInfo); 
var aCaller: PtrUInt; 
begin 
    if (self<>nil) and (Level in fFamily.fLevel) then begin 
    LogHeaderLock(Level); 
    asm 
     mov eax,[ebp+4] // retrieve caller EIP from push ebp; mov ebp,esp 
     sub eax,5  // ignore call TSynLog.Enter op codes 
     mov aCaller,eax 
    end; 
    TSynMapFile.Log(fWriter,aCaller); // here it will call TSynMapFile for the current exe 
    LogTrailerUnLock(Level); 
    end; 
end; 

このメソッドは、呼び出し元のアドレスを取得し、そのユニット名、メソッド名、および行番号を記録できます。

+0

Jediのデバッグコードなどを追加することなく、通常のデバッグビルド(または外部のマップを使用したリリース)からコールスタックをログに記録できますか?特定の状況では、どこから呼び出されたかを記録して報告できるコードを持つことは非常に便利です。 –

+0

@DavidMはい、これを行うことができます。 .map/.mabが添付されていない場合は、16進アドレスを記録します。 LogViewツールは、.exeと一致する既存の.mapファイルからソースコード行を取得できます。しかし、私たちの.mab形式は非常に小さいので、コンパイル時に.exeに埋め込まない理由はありません。 –

+0

@ArnaudBouchezコンパイル時に.exeに埋め込む方法を教えてください。 – SOUser

関連する問題