起源:

用习惯了c#之Exception的StackTrace,在程序出异常crash时候能够以其定位出问题的模块及行号,用回Delphi 2009,发现没有这东西。

显然,在编译环境日新月异的今天,是不科学的。分析Delphi的Exception,发现些线索:StackTrace。

应该有戏!

继续下去,验证输出这个StackTrace,它是空的,里面没有预想要的内容。再深究去,发现并没想象那么容易,它扯到不少蛋。

1、Exception类

Delphi 2009中,StackTrace是如此定义的,与它一起的还有几个var:

  Exception = class(TObject)
private
...
protected
...
public
...
property StackTrace: string read GetStackTrace;
property StackInfo: Pointer read FStackInfo;
{$IFDEF MSWINDOWS}
class var
// Hook this function to return an opaque data structure that contains stack information
// for the given exception information record. This function will be called when the
// exception is about to be raised or if this is an external exception such as an
// Access Violation, called soon after the object is created.
GetExceptionStackInfoProc: function (P: PExceptionRecord): Pointer;
// This function is called to return a string representation of the above opaque
// data structure
GetStackInfoStringProc: function (Info: Pointer): string;
// This function is called when the destructor is called to clean up any data associated
// with the given opaque data structure.
CleanUpStackInfoProc: procedure (Info: Pointer);
// Use this function to raise an exception instance from within an exception handler and
// you want to "acquire" the active exception and chain it to the new exception and preserve
// the context. This will cause the FInnerException field to get set with the exception
// in currently in play.
// You should only call this procedure from within an except block where the this new
// exception is expected to be handled elsewhere.
class procedure RaiseOuterException(E: Exception); static;
// Provide another method that does the same thing as RaiseOuterException, but uses the
// C++ vernacular of "throw"
class procedure ThrowOuterException(E: Exception); static;
{$ENDIF}
end;

明明白白的说,我东西给你了,你要用,自己想办法。你编译环境都不能实现,让我想什么办法?去它主页上看看:

蛋疼之极,欲用StackTrace,它居然要求我们用第三方的解决方案。如此不负责任!

好吧,上JEDI。

2、JclDebug

StackOverflow是个技术的绝佳去处,曾在其上受益不少,再去找找,果然有所得。

有个家伙封装了实现方法,借鉴下来,代码如下:

unit StackTrace;

interface

uses
SysUtils, Classes, JclDebug; implementation function GetExceptionStackInfoProc(P: PExceptionRecord): Pointer;
var
LLines: TStringList;
LText: String;
LResult: PChar;
begin
LLines := TStringList.Create;
try
JclLastExceptStackListToStrings(LLines, True, True, True, True);
LText := LLines.Text;
LResult := StrAlloc(Length(LText));
StrCopy(LResult, PChar(LText));
Result := LResult;
finally
LLines.Free;
end;
end; function GetStackInfoStringProc(Info: Pointer): string;
begin
Result := string(PChar(Info));
end; procedure CleanUpStackInfoProc(Info: Pointer);
begin
StrDispose(PChar(Info));
end; initialization
// Start the Jcl exception tracking and register our Exception
// stack trace provider.
if JclStartExceptionTracking then
begin
Exception.GetExceptionStackInfoProc := GetExceptionStackInfoProc;
Exception.GetStackInfoStringProc := GetStackInfoStringProc;
Exception.CleanUpStackInfoProc := CleanUpStackInfoProc;
end; finalization
// Stop Jcl exception tracking and unregister our provider.
if JclExceptionTrackingActive then
begin
Exception.GetExceptionStackInfoProc := nil;
Exception.GetStackInfoStringProc := nil;
Exception.CleanUpStackInfoProc := nil;
JclStopExceptionTracking;
end; end.

很是优美。但单步去跟,发现GetExceptionStackInfoProc中,其返回值为空。

作者也发现了,所幸另个人解决这个问题,替换其函数如下:

function GetExceptionStackInfoProc(P: PExceptionRecord): Pointer;
var
LLines: TStringList;
LText: String;
LResult: PChar;
jcl_sil: TJclStackInfoList;
begin
LLines := TStringList.Create;
try
jcl_sil := TJclStackInfoList.Create(True, , p.ExceptAddr, False, nil, nil);
try
jcl_sil.AddToStrings(LLines, true, true, true, true);
finally
FreeAndNil(jcl_sil);
end;
LText := LLines.Text;
LResult := StrAlloc(Length(LText));
StrCopy(LResult, PChar(LText));
Result := LResult;
finally
LLines.Free;
end;
end;

验证OK,解决问题!

这样,可以挂接Application.OnException,自个处理程序的Crash异常了。

注意事项:用JEDI求堆栈信息,须设置Delphi工程属性之Linking->Map file值为Detailed,它是基于解析map文件生成数据:

参考资料:

System.SysUtils.Exception.StackTrace

JEDI Code Library

Delphi - Trying to get StackTrace for an exception

Delphi:Exception输出堆栈信息的更多相关文章

  1. Slf4j 打日志的问题 Exception 没有堆栈信息

    Slf4j 打日志的问题 Exception 没有堆栈信息 发现线上环境有的Exception堆栈信息没打出来,只有异常信息没有堆栈信息,难以定位 一般情况下日志这么打 log.info(" ...

  2. C++ crash 堆栈信息获取(三篇文章)

    最近在做程序异常时堆栈信息获取相关工作,上一篇文章成功的在程序creash时写下了dump文件,而有些情况写dump文件是 不可以的,比如在jni开发时,C++只做底层处理,而整个项目是android ...

  3. 在Linux与Windows上获取当前堆栈信息

    在编写稳定可靠的软件服务时经常用到输出堆栈信息,以便用户/开发者获取准确的运行信息.常用在日志输出,错误报告,异常检测. 在Linux有比较简便的函数获取堆栈信息: #include <stdi ...

  4. C++ crash 堆栈信息获取

    最近在做程序异常时堆栈信息获取相关工作,上一篇文章成功的在程序creash时写下了dump文件,而有些情况写dump文件是 不可以的,比如在jni开发时,C++只做底层处理,而整个项目是android ...

  5. C++ crash 堆栈信息获取(三篇)

    最近在做程序异常时堆栈信息获取相关工作,上一篇文章成功的在程序creash时写下了dump文件,而有些情况写dump文件是 不可以的,比如在jni开发时,C++只做底层处理,而整个项目是android ...

  6. 使用log4j的时候如何输出printStackTrace()的堆栈信息

    使用log4j的时候如何输出printStackTrace()的堆栈信息 研究了一下发现很简单,如下: log.error(e.getMessage(),e); 输出信息如下: 2009-05-11 ...

  7. Delphi中使用Dos窗口输出调试信息

    在项目文件 *.DPR (Project->View Source)  里加上{$APPTYPE   CONSOLE} 然后,在需要输出处加上 Writeln(‘your debug messa ...

  8. Delphi之Exception获得错误信息(简单好理解)

    Delphi之Exception获得错误信息 相关资料: http://www.cnblogs.com/hackpig/archive/2010/02/15/1668547.html 实例代码: 1 ...

  9. Delphi RAD Berlin OutputDebugString 输出调试信息

    Delphi RAD Berlin Event Log.OutputDebugString 输出调试信息,仅在win VCL下可以用.OutputDebugString(PChar('hellowor ...

随机推荐

  1. jinjia

    https://www.cnblogs.com/dachenzi/p/8242713.html

  2. vue 源码阅读记录

    0.webpack默认引入的是vue.runtime.common.js,并不是vue.js,功能有略微差别,不影响使用 1.阅读由ts编译后的js: 入口>构造函数 >定义各类方法 &g ...

  3. javascript:图片转base64

    第一种: <!DOCTYPE html><html> <head> <meta charset="utf-8"> <meta ...

  4. tips___代码规范

    函数变量尽可能置于最小作用域内,并在变量声明时进行初始化 变量声明的位置最好离第一次使用的位置越近越好:应使用初始化的方式代替声明再赋值. int x=0; rather than  int x; x ...

  5. Raft算法和Gossip协议

    简单介绍下集群数据同步,集群监控用到的两种常见算法. Raft算法 raft 集群中的每个节点都可以根据集群运行的情况在三种状态间切换:follower, candidate 与 leader.lea ...

  6. Oracle相关文章

    1.oracle 11g常用命令 2.Oracle的在windows下的安装及使用 3.Oracle scott账户被锁定,scott默认密码,sys,system默认密码 4.NaviCat Pri ...

  7. ReactiveX 学习笔记(8)错误处理和 To 操作符

    Error Handling Operators Operators to Convert Observables 本文的主题为对 Observable 进行错误处理的操作符以及转换 Observab ...

  8. 前后台联调,突然所有的接口请求状态为200,但response什么都没有只有一句灰色的英文

    问题解决了,图就下次遇到截图补上: 解决问题的方法,是让后台查看数据库是否锁库,或者更改什么配置文件例如.xml文件,还有就是ip错误:

  9. asp.net 服务器 上传文件到 FTP服务器

    private string ftpServerIP = "服务器ip";//服务器ip private string ftpUserID = "ftp的用户名" ...

  10. C# 汉字转拼音(全拼)

    C# 汉字转拼音(全拼)     很多时候我们需要把汉字转换成拼音,比如姓名.城市名等.网上搜索了一把,把汉字转成拼音的代码很多,但大多都只是把汉字转成了拼音的首字母,比如把“深圳”转成了“sz”.那 ...