to beta:
--------
如果在 try 中出现了异常,那么程序会从出错的地点直接跳到内部的出错处理部分,
然后再跳到我们的 finally 部分(严格来说,过程不是这样,不过你可以认为是这样,
对于处理本问题是适用的,要是有朋友想打破沙锅问到底,我再罗嗦也不迟),
-------
的确不是这样,如果是try-finally-end块,则一旦发生异常,最先进入的并不是finally-end块,而是外层的第一个要处理该异常的except-end块。
在外层处理异常时,一个RTLUnwind()的调用将总是发生,这是异常展开。一个finally-end块总是处理被展开的异常(而不是被触发的异常)。在一个finally-end块处理完RTLUnwind()展开的异常后,才会回到except-end块,来处理用户的异常处理代码。
在.exe和.dll的初始化代码中,SetExceptionHandler()用于设置一个顶层异常处理句柄。这使得一个异常无论如何,总会被展开。也就是说,至少会被_ExceptionHandler()例程展开。finally-end总会得到响应异常的机会,而except-end却不一定(需要加上SysUtils.pas单元)。
--------
这就是说,我们完全可以在 finally 的第一行判断 eax 的值,就可以知道刚才
是否发生异常了。
-------
这绝对是不安全的,eax的值并不能保证。不过有一点可以肯定,如果代码正常执行到finally-end,eax的确为0。
-------
那何不干脆让do
Log 没有参数,直接在do
Log 里面判断 eax 不也可以吗?还是不
行,DoLog 在执行第一行用户代码前,还有动作,而如果你的过程没有参数的话,这些
动作很有可能修改 eax。
-------
其实这是个好办法。要让“DoLog 在执行第一行用户代码前,没有动作”,其实并不难。──如果一个过程没有入口参数,也没有局部变量,并且是完全汇编例程,那么,它在第一行代码前就什么也没有。例如这样:
procedure _DoLog(EAX
WORD);
begin
// if you want, you cando
any...
end;
proceduredo
Log;
asm
call _DoLog
end;
procedure Work;
begin
try
finally
do
Log;
// OK. ^.^
end;
end;
-------
//DoLog 参数看起来及其不爽,加把油搞定他......
没有参数怎么判断?除非你想麻烦点,DoLog 无参数版本:
-------
哈哈,这个版本也不好。还是变态。^.^
to zqw0117,
----------------
哎,你的建议其实有非常简单的解决方法,也是比较常用的。
{$IFOPT D+}
log_Exception....
{$else
}
do
your code....
{$END}
这就是编译调试版本和发布版本的不同之处。
to yyanghhong,
---------------------
我不了解java的异常机制。但是Delphi的异常处理机制的确就是分层的。Global Exception Handling只是留给开发者的一个接口而已,Delphi内核是不用它来处理异常的。
正是因为delphi是分层处理异常,才使得JCLDebug或ExceptionalMagic等可用。要不,内核不支持的话,外部应用又如何打印exception Stack呢?
此外,Delphi分层处理异常,是基于OS的SEH机制的。并不是Delphi自身的机制,准确地说,Delphi只是实现了它。
其它,
--------
我想想代码,或者有别的方法来实现一个HaveException()函数。