当函数中出现异常时,TStrings返回为“无法访问的值”

时间:2014-08-14 14:28:34

标签: delphi

有人可以帮我解释为什么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

1 个答案:

答案 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;

以下是执行顺序:

  1. 由于S是局部变量,因此在初始化之前,其值是不确定的。这是该代码开始执行的状态。
  2. 调用GetStrings函数。
  3. GetStrings引发了异常。这意味着GetStrings不会将执行返回给调用者,因此导致S永远不会被分配。
  4. finally块未执行,因为从未尝试过它。
  5. 接下来,执行except块,S具有不确定的值,这是您观察到的。
  6. 实际上,编译器应警告(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}}块将能够引用该对象。