有人可以帮我解释为什么TStrings被返回为"无法访问的价值"何时在欠功能中引发异常?
function GetStrings():TStrings;
begin
result := TStringList.Create;
try
raise exception.Create('Error Message');
except
FreeAndNil(result);
raise
end;
end;
procedure TFormMain.Button1Click(Sender: TObject);
var
S : TStrings;
begin
try
S := GetStrings;
try
//Do awesome stuff
finally
FreeAndNil(S)
end;
except
//Debug watch: S = "Inaccessible value"
Assert(S = nil, 'Assertion failure, S should be nil');
end;
end;
函数GetStrings
也返回"无法访问的值"如果我在重新启动例外之前没有给FreeAndNil(result);
打电话。然而,我的手上也有内存泄漏:-O
答案 0 :(得分:6)
try
S := GetStrings;
try
//Do awesome stuff
finally
FreeAndNil(S)
end;
except
//Debug watch: S = "Inaccessible value"
Assert(S = nil, 'Assertion failure, S should be nil');
end;
以下是执行顺序:
S
是局部变量,因此在初始化之前,其值是不确定的。这是该代码开始执行的状态。GetStrings
函数。GetStrings
引发了异常。这意味着GetStrings
不会将执行返回给调用者,因此导致S
永远不会被分配。finally
块未执行,因为从未尝试过它。except
块,S
具有不确定的值,这是您观察到的。实际上,编译器应警告(W1036)S
块中引用except
时可能尚未初始化S
。但它似乎无法做到这一点,这是相当可悲的。
如果您希望能够在except
区块中引用try/finally
,则需要将其嵌套在S := GetStrings;
try
try
//Do awesome stuff
except
//Do stuff with S
Assert(S <> nil);
end;
finally
FreeAndNil(S)
end;
内。
S
另一种思考方式是S
仅在分配给try/except
的代码和销毁该对象的代码之间有意义。结果是try/finally
必须嵌套在except
内,如果{{1}}块将能够引用该对象。