Delphi Tokyo异常会阻止设置功能结果

Mol*_*nik 15 delphi exception

发现Delphi Tokyo中的异常处理与以前的Delphi版本略有不同.

function FuncTest: integer;
begin
  Result := 1;
  try
    raise Exception.Create('Error Message');
  finally
    Result := 2;
  end;
end;

function Test:integer;
begin
  Result:=0;
  try
    Result:=FuncTest;
  finally
    ShowMessage(Result.ToString);
  end;
end;
Run Code Online (Sandbox Code Playgroud)

在早期的Delphi版本中,消息框显示"2",东京 - "0".这是一个东京错误还是不应该像这样处理异常?

Dav*_*nan 15

东京的行为是正确的.引发异常的函数不返回值.到目前为止,您一直依赖于实现细节.

考虑以下代码:

Result:=FuncTest;
Run Code Online (Sandbox Code Playgroud)

执行如下:

  1. FuncTest 叫做.
  2. Result 被安排了.

现在,因为步骤1引发异常,所以步骤2不会执行.

如果有的话,我会说你从早期版本报告的行为是可疑的.在这个功能:

function Test:integer;
begin
  Result:=0;
  try
    Result:=FuncTest;
  finally
    ShowMessage(Result.ToString);
  end;
end;
Run Code Online (Sandbox Code Playgroud)

该语句Result:=FuncTest引发异常,因此Result不应该被该语句修改.另一种思考方式是调用函数但不执行赋值.


Delphi ABI的一个问题是函数返回值有时被实现为隐式var参数.这意味着任务可能会也可能不会发生.展示:

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

type
  TRec1 = record
    X1: NativeInt;
  end;

  TRec2 = record
    X1: NativeInt;
    X2: NativeInt;
  end;

function GetRec1: TRec1;
begin
  Result.X1 := 1;
  raise Exception.Create('');
end;

function GetRec2: TRec2;
begin
  Result.X1 := 1;
  raise Exception.Create('');
end;

procedure Main;
var
  Rec1: TRec1;
  Rec2: TRec2;
begin
  Rec1 := Default(TRec1);
  Writeln(Rec1.X1);
  try
    Rec1 := GetRec1;
  except
  end;
  Writeln(Rec1.X1);

  Rec2 := Default(TRec2);
  Writeln(Rec2.X1);
  try
    Rec2 := GetRec2;
  except
  end;
  Writeln(Rec2.X1);
end;

begin
  Main;
  Readln;
end.
Run Code Online (Sandbox Code Playgroud)

这输出:

0
0
0
1

这是相当令人失望的.不应该修改调用者的变量,但是使用隐式var参数而不是值返回允许这种泄漏.在我看来,这是Delphi ABI设计中的一个严重缺陷,这是一个你在大多数其他语言中都找不到的缺陷.


在您的代码中,没有var参数,因为返回类型在寄存器中传输.在这种情况下,任何输出的Delphi版本都会2被破坏.

从根本上说,你的代码在预期中是错误的.如果函数引发异常,则必须假定返回值是错误定义的.

最后,你的代码输出0在XE3和XE7中,所以我想知道你需要多远才能看到一个值2.