Delphi:Exception输出堆栈信息
起源:
用习惯了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
Delphi - Trying to get StackTrace for an exception
Delphi:Exception输出堆栈信息的更多相关文章
- Slf4j 打日志的问题 Exception 没有堆栈信息
Slf4j 打日志的问题 Exception 没有堆栈信息 发现线上环境有的Exception堆栈信息没打出来,只有异常信息没有堆栈信息,难以定位 一般情况下日志这么打 log.info(" ...
- C++ crash 堆栈信息获取(三篇文章)
最近在做程序异常时堆栈信息获取相关工作,上一篇文章成功的在程序creash时写下了dump文件,而有些情况写dump文件是 不可以的,比如在jni开发时,C++只做底层处理,而整个项目是android ...
- 在Linux与Windows上获取当前堆栈信息
在编写稳定可靠的软件服务时经常用到输出堆栈信息,以便用户/开发者获取准确的运行信息.常用在日志输出,错误报告,异常检测. 在Linux有比较简便的函数获取堆栈信息: #include <stdi ...
- C++ crash 堆栈信息获取
最近在做程序异常时堆栈信息获取相关工作,上一篇文章成功的在程序creash时写下了dump文件,而有些情况写dump文件是 不可以的,比如在jni开发时,C++只做底层处理,而整个项目是android ...
- C++ crash 堆栈信息获取(三篇)
最近在做程序异常时堆栈信息获取相关工作,上一篇文章成功的在程序creash时写下了dump文件,而有些情况写dump文件是 不可以的,比如在jni开发时,C++只做底层处理,而整个项目是android ...
- 使用log4j的时候如何输出printStackTrace()的堆栈信息
使用log4j的时候如何输出printStackTrace()的堆栈信息 研究了一下发现很简单,如下: log.error(e.getMessage(),e); 输出信息如下: 2009-05-11 ...
- Delphi中使用Dos窗口输出调试信息
在项目文件 *.DPR (Project->View Source) 里加上{$APPTYPE CONSOLE} 然后,在需要输出处加上 Writeln(‘your debug messa ...
- Delphi之Exception获得错误信息(简单好理解)
Delphi之Exception获得错误信息 相关资料: http://www.cnblogs.com/hackpig/archive/2010/02/15/1668547.html 实例代码: 1 ...
- Delphi RAD Berlin OutputDebugString 输出调试信息
Delphi RAD Berlin Event Log.OutputDebugString 输出调试信息,仅在win VCL下可以用.OutputDebugString(PChar('hellowor ...
随机推荐
- 【Noip模拟 20161004】局域网
问题描述 所有SZSZ 学生翘首以盼的新教学楼总算快要竣工了,接下来到了网络布线的时候.网络系统的总布局是由nn台计算机组成的有线局域网,每根网线长度为dd,正常情况下,网线是可以缠绕使其变短但是不能 ...
- linux文本处理笔记
cut: 按列操作文本 sort: 排序 uniq: 去重,去除连续重复行 cut -d 'delimiter' -f start-end filename.txt # -d 表示分割符号,del ...
- JAVA_连接池、DataSource、JNDI
1.连接池 Connection的取得和开放是代价比较高的处理,解决这个问题的方法是连接池. 连接池就是事先取得一定数量的Connection,程序执行处理的时候不是新建Connectio ...
- 【BUG记录】记一次游戏越来越卡的BUG
U3D的MOBA项目,测试过程中,10分钟以后,游戏帧率开始缓慢下降,约3-5分钟后,由60帧下降到小于10帧,编辑器模式. 打开profiler,看到CPU占用非常高,每帧都有24K的GC, 时间占 ...
- Nginx性能优化
一.编译安装过程优化 1.减小Nginx编译后的文件大小 在编译Nginx时,默认以debug模式进行,而在debug模式下会插入很多跟踪和ASSERT之类的信息,编译完成后,一个Nginx要有好几兆 ...
- mycat 分库分表
单库分表已经在上篇写过了,这次写个分库分表,不同在于配置文件上的一点点不同 <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> &l ...
- RabbitMQ系列教程之三:发布/订阅(Publish/Subscribe)(转载)
RabbitMQ系列教程之三:发布/订阅(Publish/Subscribe) (本教程是使用Net客户端,也就是针对微软技术平台的) 在前一个教程中,我们创建了一个工作队列.工作队列背后的假设是每个 ...
- 217/219. Contains Duplicate /Contains Duplicate II
原文题目: 217. Contains Duplicate 219. Contains Duplicate II 读题: 217只要找出是否有重复值, 219找出重复值,且要判断两者索引之差是否小于k ...
- 传输层——TCP报文头介绍
16位源端口号 16位目的端口号 32位序列号 32位确认序列号 4位头部长度 保留6位 U R G A C K P S H R S T S Y N F I N 16位窗口大小 16位检验和 16位紧 ...
- 2018面向对象程序设计(Java)第11周学习指导及要求
2018面向对象程序设计(Java)第11周学习指导及要求 (2018.11.8-2018.11.11) 学习目标 (1) 掌握Vetor.Stack.Hashtable三个类的用途及常用API: ...