请大家看看我这样写的异常处理对不对!!! ( 积分: 50 )

  • 主题发起人 主题发起人 cnsyj
  • 开始时间 开始时间
C

cnsyj

Unregistered / Unconfirmed
GUEST, unregistred user!
请大家看看我这样写的异常处理对不对!!!
try
try
tmpread:=TRegistry.Create;
tmplist:=TStringList.Create;
tmpread.RootKey:=HKEY_LOCAL_MACHINE;
if tmpread.openkey('SOFTWARE/Microsoft/Windows/CurrentVersion/run',false) then
begin
tmpread.GetValueNames(tmplist);
tmpint:=tmplist.Count;
while tmpint > 0 do
begin
tmpint:=tmpint-1;
tmpa:=tmplist.ValueFromIndex[tmpint];
tmpb:=tmpread.ReadString(tmplist.Strings[tmpint]);
with listview1.Items.Add do
begin
caption:=tmpa;
subitems.Add(tmpb);
end;
end;
end;
finally
tmplist.Free;
tmpread.Free;
end;
except
tmplist.Free;
tmpread.Free;
showmessage('读取HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/run下数据错误!')
end;
 
不对,正确的写法是
tmpread:=TRegistry.Create;
try
tmplist:=TStringList.Create;
try
try
....
except
showmessage('读取HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/run下数据错误!');
end;
finally
tmplist.Free;
end;
finally
tmpread.Free;
end;
 
我觉得这样写,也没什么大错
 
1、你的try finally在create对象外面,这样会造成一个问题,如果create(你有两个对象在创建,假设其中之一)没有成功,还是会执行finally块里面的
tmplist.Free;
tmpread.Free;
这两句都会被执行!假设,tmplist创建失败(但tmpread创建是成功的),当执行到tmplist.free的时候,会抛出异常(因为对象没有创建,所以访问对象的Free方法就会出现著名的AV错误),那么下面的tmpread.free永远不会得到执行。

2、你的代码等于是
try
try
...
finally
释放对象
end;
except
释放对象
end;
请记住,任何时候,哪怕是触发了异常,finally块也会执行的,这个时候释放对象的代码会得到执行,而执行完后,跳转到except下,会再次执行释放对象的操作,请问释放两次会不会成功?

3、楼主如果不信你的代码有问题,自己抛一个异常看看结果如何就知道了:

try
try
tmpread:=TRegistry.Create;
tmplist:=TStringList.Create;
tmpread.RootKey:=HKEY_LOCAL_MACHINE;
[red]raise Exception.Create('我手工抛一个异常,测试一下try代码块是否正常');[/red]
if tmpread.openkey('SOFTWARE/Microsoft/Windows/CurrentVersion/run',false) then
begin
tmpread.GetValueNames(tmplist);
tmpint:=tmplist.Count;
while tmpint > 0 do
begin
tmpint:=tmpint-1;
tmpa:=tmplist.ValueFromIndex[tmpint];
tmpb:=tmpread.ReadString(tmplist.Strings[tmpint]);
with listview1.Items.Add do
begin
caption:=tmpa;
subitems.Add(tmpb);
end;
end;
end;
finally
tmplist.Free;
tmpread.Free;
end;
except
tmplist.Free;
tmpread.Free;
showmessage('读取HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/run下数据错误!')
end;
 
收藏此贴 [:D]
 
zqw0117正确,代码可简化一下。

tmpread:=TRegistry.Create;
tmplist:=TStringList.Create;
try
try
....
except
showmessage('读取HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/run下数据错误!');
end;
finally
tmplist.Free;
tmpread.Free;
end;
 
to nicai_wgl,
其实这样仍然有我说的隐患的:
tmpread:=TRegistry.Create
//假设这句执行正常
tmplist:=TStringList.Create
//这句执行失败
try
try
....
except
showmessage('读取HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/run下数据错误!');
end;
finally
tmplist.Free
//这句和下面这句都不会得到执行,因此
tmpread.Free
//tmpread对象将不会得到释放
end


所以,最好的办法是对每个创建的对象都用单独的try finally块包裹起来!这样才是最正确的做法。
 
如果楼主需要将
tmpread:=TRegistry.Create;
tmplist:=TStringList.Create;
这两句可能的失败也包括在except里面,应该这样写
try
tmpread:=TRegistry.Create;
try
tmplist:=TStringList.Create;
try
...
finally
tmplist.Free;
end;
finally
tmpread.free;
end;
except
///异常处理
end;
 
接受答案了.
 
后退
顶部