大家看一下下面的代码,如果调用test方法,仍然会抛出异常,请问是为什么?procedure throw;
begin
try
raise Exception.Create( 'test' );
except
on e: Exception do
begin
raise e;
end;
end;
end;procedure test;
begin
try
throw;
except
on e:Exception do
AddMsg( e.Message );
end;
end;然而改一下,就没问题了procedure throw;
begin
try
raise Exception.Create( 'test' );
except
on e: Exception do
begin
raise; //这里改成这样
end;
end;
end;procedure test;
begin
try
throw;
except
on e:Exception do
AddMsg( e.Message );
end;
end;
begin
try
raise Exception.Create( 'test' );
except
on e: Exception do
begin
raise e;
end;
end;
end;procedure test;
begin
try
throw;
except
on e:Exception do
AddMsg( e.Message );
end;
end;然而改一下,就没问题了procedure throw;
begin
try
raise Exception.Create( 'test' );
except
on e: Exception do
begin
raise; //这里改成这样
end;
end;
end;procedure test;
begin
try
throw;
except
on e:Exception do
AddMsg( e.Message );
end;
end;
解决方案 »
- 如何打开bpl文件
- 怎么将memo里逐行记录循环写DBGrid各列中
- ListView的简单问题,向各位请教,谢谢!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- Delphi对TXT的操作(求助)
- 怎样实现鼠标移到一个SpeedButton上时会显示一个提示信息!
- Error creating form:Invalid stream format.
- 包装一个时钟类,显示日期和时间。从TPanel继承,把TTimer作为成员数据
- 如果你水平不错,请看!
- delphi报表输出中如何能让他自动换行?(是中文的)还有其它问题高手请进!
- 关于Variant的类型值
- TToolbar控件应用问题..
- 关于存储过程中的变量和参数
begin
try
raise Exception.Create( 'test' );
except
on e: Exception do
AddMsg( e.Message );
end;
end;
而上面一种写法中所抛出的异常经过throw中的try...except处理后,异常对象e就会被自动销毁。此时再在test中尝试访问e对象,会遇到“内存越界”错误,因为此时e已经不存在了Delphi中的异常对象在被处理后就会自动销毁,除非它被重新抛出。
重新抛出的语句就是raise;
你说如果raise就不会报地址错,我用的不正是raise吗?
第一种写法throw.except捕捉到异常e后,如果没有使用继承raise(raise后不加参数)而是raise在后跟了其它值的时候(包括raise e),会先把e标志成已经捕捉到过的异常。这样,下次捕捉到异常之前,首先会清理标为已捕捉到过的异常的对象,从而避免memory leak。于是在test.except中,捕捉到的异常对象实际上已经被销毁了,test.except结束后试图清理异常对象e时,又会因为该对象销毁已经被销毁了而产生另外一个异常,也就是说,在你的test.except结束时,发生了一个你没预料到的异常而第二种写法直接将继承上一次异常,与第一种写法引发的方式不同,不把这个对象标志成已捕捉过的,于是下次捕捉异常之前就不会试图清理它实际上的处理机制远比我说的复杂许多(比如不是通过标记异常对象本身来确定是否释放它的,而是通过不同的引发调用方式实现的),不过发生的顺序大体上没问题,这样只是有助于理解而已