我正在使用DLL,有时会引发未处理的异常.我使用madExcept来检测和调试有缺陷的代码,但是当我最终部署我的DLL时,我希望在DLL中包含我自己的全局异常处理程序来记录异常.
所以问题是如何在我的Delphi DLL中设置全局异常处理程序?
Mas*_*ler 10
"全局异常处理程序"的概念在DLL中并不像VCL中存在的那样存在.要理解原因,请记住异常通过展开堆栈来传播,直到找到处理程序.VCL可以安装一个全局异常处理程序,因为在VCL应用程序中,发生的所有事情(不包括启动和关闭)都会TApplication.Run在调用堆栈中的某个位置,而这就是它放置异常处理程序的位置.由于你的DLL没有这样的单一中心点,你不能这样做.
你可以做的是在你的DLL中的某个地方设置一个"中央异常处理程序例程".它应该将一个Exception对象作为参数.然后对所有导出的例程执行类似的操作:
procedure MyExportedRoutine(param: integer);
begin
try
//do normal stuff
except
on E: Exception do
CentralExeptionHandler(E);
end;
end;
Run Code Online (Sandbox Code Playgroud)
除非你使用COM,否则这是你能做的最好的事情.如果您正在编写COM DLL,请使用safecall调用约定标记您的接口方法,编译器将为您静默生成负责异常传播的代码.
Bar*_*lly 10
"全局异常处理程序"到底是什么意思?
Windows结构化异常处理(SEH)(32位)通过遍历发生异常的线程的异常处理程序链来查找处理程序.异常处理程序链是记录的链接列表,其中的头部位于FS:[0]; 记录通常在堆栈上分配,每次按下try并在退出受保护块时弹出.每个异常记录都有一个回调例程; Windows在其搜索阶段调用此例程以及异常的详细信息,以确定链的这个"级别"是否将"处理"异常.Windows然后通过再次遍历异常链将调用堆栈展开到该点,使用不同的值调用每个回调,让它知道展开正在进行,直到它到达选择处理异常的处理程序.如果没有找到处理程序,则该过程很难终止,无需通知.通常这不会发生; 操作系统在堆栈底部(链中的最后一个元素)安装自己的最后机会处理程序,这通常会弹出熟悉的Windows"此程序遇到问题"对话框.但是如果事情变得非常腐败,或者异常处理程序链已经被删除了,那么这个过程会很难实现.
因此,从这个简短的Windows异常处理概述中,应该清楚的是,没有单一的"全局"处理程序,只有一个处理程序列表,每个线程一个列表(FS寄存器是线程上下文的一部分); 并且"最后机会"处理程序是最早安装在堆栈中的处理程序.捕获DLL中发生的异常的最简单方法是在每个入口点立即安装异常处理程序.有关如何执行此操作的详细信息,请参阅Mason的答案(使用try/ except); 但要注意,如果你的DLL回调到其他地方(例如通过回调例程),那么你可能会捕获那些不是"意味着"的异常,而不是由你的代码引起的异常.(期望异常通过DLL级别的第三方代码进行传播是不好的方式,但它可能会发生.)