Zachowanie Tokio jest poprawne. Funkcja, która podnosi wyjątek, nie zwraca wartości. Do tej pory polegałeś na szczegółach implementacji.
Rozważmy następujący kod:
Result:=FuncTest;
ten wykonuje się następująco:
FuncTest
jest tzw.
Result
jest przypisany.
Teraz, ponieważ krok 1 wywołuje wyjątek, krok 2 nie jest wykonywany.
Jeśli cokolwiek, chciałbym powiedzieć, że zachowanie zgłaszane przez wcześniejsze wersje jest wątpliwe. W tej funkcji:
function Test:integer;
begin
Result:=0;
try
Result:=FuncTest;
finally
ShowMessage(Result.ToString);
end;
end;
Oświadczenie Result:=FuncTest
podnosi wyjątek i tak Result
nie powinny być modyfikowane przez tego oświadczenia. Innym sposobem, aby o tym pomyśleć, jest wywołanie funkcji, ale przypisanie nie jest wykonywane.
Jednym z problemów związanych z Delphi ABI jest to, że funkcja wartości powrotne są wdrażane jako ukrytych var
parametrów. Co oznacza, że zadanie może się zdarzyć lub nie. Aby wykazać, że:
{$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.
This wyjścia:
0
0
0
1
co jest raczej rozczarowujące. Zmodyfikowanie zmiennej wywołującej nie powinno być możliwe, ale użycie niejawnego parametru var
zamiast powrotu wartości umożliwia takie przeciekanie. Moim zdaniem jest to poważna usterka w projekcie Delphi ABI, wada, której nie można znaleźć w większości innych języków.
W kodzie nie ma parametr var
ponieważ typ zwracany jest przekazywana w rejestrze. W takim przypadku każda wersja Delphi, która wyprowadza 2
, jest zepsuta.
Zasadniczo twój kod jest błędny w swoich oczekiwaniach. Jeśli funkcja wywołuje wyjątek, musisz założyć, że wartość zwracana jest źle zdefiniowana.
Wreszcie, twój kod wyprowadza 0
w XE3 i XE7, więc zastanawiam się, jak daleko wstecz musisz iść, aby zobaczyć wartość 2
.
Nie mam wcześniejszej wersji Delphi, ale myślę, że to XE2, gdzie został wprowadzony kompilator x64.A ma kod, który opierał się na fakcie, że FuncTest zwraca 1 (bez bloku try) lub 2. Ok dostałem to, nie więcej funkcji zgłaszających wyjątki, tylko procedury. – Molochnik
To jest w porządku, aby funkcja zgłaszała wyjątki. Co jest złe, to oczekiwać zwrotu wartości w takim przypadku. W tym przypadku, ponieważ typ powrotu pasuje do rejestru, ABI jest w porządku, nie ma problemów z parametrem "var". Ale tak, XE2 64 bit miał kilka dobrych problemów. –
Masz na myśli to, że jeśli funkcja zwróciła e, g, rekord, to nie byłoby problemu? – Molochnik