如何在运行时获取行号

mic*_*l85 8 delphi debugging

在Delphi中可以在运行时获取源行号吗?我知道JCL调试,但我想避免使用它.Assert也不是我想要的.我想得到这样的东西,GetLineNumber将得到源代码行.是否可以在没有MAP文件的情况下执行此操作(无论如何,当我使用Assert时会生成MAP文件)?有什么例子吗?

function GetLineNumber: integer;
begin
  ???
end;

procedure ThisWouldBeGreat;
begin
  if not SomeCondition then
    LogMemo.Lines.Add('Error on line: ' + IntToStr(GetLineNumber));
end;

procedure ThatsWhatIWont;
begin
  Assert(not SomeCondition, 'Error');
end;
Run Code Online (Sandbox Code Playgroud)

谢谢

Rob*_*edy 11

你确实可以用Assert它.编写一个与TAssertErrorProc类型所指示的签名相匹配的过程,然后在那里做任何你想做的事情.为了保留预期的行为,您应该在完成后调用原始处理程序.

procedure MichaelAssertProc(const Message, Filename: string;
  LineNumber: Integer; ErrorAddr: Pointer);
begin
  LogMessage(...);
  SysUtils.AssertErrorHandler(Message, Filename, LineNumber, ErrorAddr);
end;
Run Code Online (Sandbox Code Playgroud)

System.AssertErrorProc在程序启动时将该过程分配给某个时间.

AssertErrorProc := MichaelAssertProc;
Run Code Online (Sandbox Code Playgroud)

  • 如果你使用这个作为调试工具跟踪错误,你会严重降低你的源代码的质量和可维护性,你将不得不在比较madExcept或其他类似的工具相当可怜,残缺的调试工具.这回答了问题的一部分,但是错过了更大的图片.与madExcept或其他类似工具相比,可怜且残缺的调试工具.这回答了问题的一部分,但错过了更大的图景. (6认同)
  • ......大卫在他的手机上说. (2认同)

Arn*_*hez 6

对于我们的日志记录和异常跟踪类,我们创建了一个.map解析器和读取器.

.map可以解析为二进制压缩版本(.mab专有格式),比原始.map小得多.例如,一个900 KB的.map文件被压缩成一个70 KB的.mab文件 - 这比zip压缩得多.

此.mab内容可以附加到.exe,执行时没有任何差异,或者最终用户.

然后你可以使用我们的日志类,或者直接使用.map/.mab阅读器类TSynMapFile.

您手头有以下方法:

  /// retrieve a .map file content, to be used e.g. with TSynLog to provide
  // additional debugging information
  // - original .map content can be saved as .mab file in a more optimized format
  TSynMapFile = class   
  public
    /// get the available debugging information
    // - will first search for a .map file in the .exe directory: if found,
    // will be read to retrieve all necessary debugging information - a .mab
    // file will be also created in the same directory (if MabCreate is TRUE)
    // - if .map is not not available, will search for the .mab file in the
    // .exe directory
    // - if no .mab is available, will search for a .mab appended to the exe 
    // - if nothing is available, will log as hexadecimal pointers, without
    // debugging information
    // - if aExeName is not specified, will use the current process executable
    constructor Create(const aExeName: TFileName=''; MabCreate: boolean=true);
    /// save all debugging information in the .mab custom binary format
    // - if no file name is specified, it will be saved as ExeName.mab
    // - this file content can be appended to the executable via SaveToExe method
    // - this function returns the created file name
    function SaveToFile(const aFileName: TFileName=''): TFileName;
    /// save all debugging informat in our custom binary format
    procedure SaveToStream(aStream: TStream);
    /// append all debugging information to an executable
    // - the executable name must be specified, because it's impossible to
    // write to the executable of a running process
    procedure SaveToExe(const aExeName: TFileName);
    /// add some debugging information according to the specified memory address
    // - will create a global TSynMapFile instance for the current process, if
    // necessary
    // - if no debugging information is available (.map or .mab), will write
    // the address as hexadecimal
    class procedure Log(W: TTextWriter; Addr: PtrUInt);
    /// retrieve a symbol according to an absolute code address
    function FindSymbol(aAddr: cardinal): integer;
    /// retrieve an unit and source line, according to an absolute code address
    function FindUnit(aAddr: cardinal; out LineNumber: integer): integer;
    /// return the symbol location according to the supplied absolute address
    // - i.e. unit name, symbol name and line number (if any), as plain text
    // - returns '' if no match found
    function FindLocation(aAddr: Cardinal): RawUTF8;
    /// all symbols associated to the executable
    property Symbols: TSynMapSymbolDynArray read fSymbol;
    /// all units, including line numbers, associated to the executable
    property Units: TSynMapUnitDynArray read fUnit;
  published
    /// the associated file name
    property FileName: TFileName read fMapFile;
    /// equals true if a .map or .mab debugging information has been loaded
    property HasDebugInfo: boolean read fHasDebugInfo;
  end;
Run Code Online (Sandbox Code Playgroud)

感谢这个课程,只需一个单元,您就可以拥有任何位置的所有源代码行.

开源,并使用Delphi 5到XE(请注意.map格式从旧版本到新版本稍有变化 - 我们的类尝试处理它).