Ответ 1
Токийское поведение правильное. Функция, которая вызывает исключение, не возвращает значение. Вы до сих пор полагались на детали реализации.
Рассмотрим этот код:
Result:=FuncTest;
Это выполняется следующим образом:
-
FuncTest
. -
Result
.
Теперь, поскольку шаг 1 вызывает исключение, шаг 2 не выполняется.
Если что-нибудь, я бы сказал, что поведение, о котором вы сообщаете из более ранних версий, сомнительно. В этой функции:
function Test:integer;
begin
Result:=0;
try
Result:=FuncTest;
finally
ShowMessage(Result.ToString);
end;
end;
Оператор 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.
Выводится:
0 0 0 1
Это довольно разочаровывает. Невозможно изменить переменную вызывающего, но использование неявного параметра var
, а не возврат значения позволяет эту утечку. На мой взгляд, это серьезный недостаток в дизайне Delphi ABI, недостаток, которого вы не найдете на большинстве других языков.
В вашем коде нет параметра var
, потому что возвращаемый тип переносится в регистр. В этом случае любая версия Delphi, которая выводит 2
, сломается.
В принципе, ваш код ошибочен в своих ожиданиях. Если функция вызывает исключение, вы должны предположить, что возвращаемое значение не определено.
Наконец, ваш код выводит 0
в XE3 и XE7, поэтому мне интересно, как далеко назад вам нужно перейти к значению 2
.