東京の動作は正しいです。例外を発生させる関数は値を返しません。これまで、実装の詳細に頼ってきました。
Result:=FuncTest;
これは、次のように実行します:
FuncTest
が呼び出され は、このコードを考えてみましょう。
Result
が割り当てられます。
ここで、ステップ1は例外を発生させるため、ステップ2は実行されません。
もし何か言えば、あなたが以前のバージョンから報告した動作は疑わしいと言います。この機能では:
function Test:integer;
begin
Result:=0;
try
Result:=FuncTest;
finally
ShowMessage(Result.ToString);
end;
end;
声明Result:=FuncTest
は、例外が発生しますので、Result
は、そのステートメントで変更すべきではありません。それを考えるもう一つの方法は、関数が呼び出されるが代入は実行されないということです。デルファイ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.
この出力:かなり残念です
0
0
0
1
を。呼び出し元の変数を変更することはできませんが、値の戻り値ではなく暗黙的なvar
パラメータを使用すると、この漏れが許容されます。私の見解では、これはデルファイABIの設計における深刻な欠陥です。これは他のほとんどの言語では見つけられない欠陥です。あなたのコードで
戻り値の型がレジスタに転送されるため、何var
パラメータがありません。この場合、2
を出力するDelphiのバージョンは破損しています。
基本的には、あなたのコードは誤解されています。関数が例外を発生させた場合は、戻り値が正しく定義されていないと想定する必要があります。
最後に、コードは0
をXE3とXE7に出力するので、どれくらい前に戻って2
の値を参照する必要があるのでしょうか。
以前のDelphiのバージョンはありませんが、x64コンパイラが導入されたのはXE2だと思います。Aは、FuncTestが1(tryブロックなし)または2を返すという事実に依存するコードを持っています。私はそれを取得しました。例外は発生しません。 – Molochnik
関数が例外を発生させても問題ありません。間違っているのは、その場合に値が返されることを期待することです。この場合、戻り値の型はレジスタに収まるため、ABIは問題ありません。「var」パラメータは発行されません。しかし、はい、XE2 64ビットはいくつか良い点がありました。 –
あなたは関数がe、g、レコードを返した場合、問題はないだろうということを意味しますか? – Molochnik