Hành vi của Tokyo là chính xác. Một hàm làm tăng một ngoại lệ không trả về một giá trị. Bạn đã từng dựa vào chi tiết triển khai.
xem xét mã này:
Result:=FuncTest;
này thực hiện như sau:
FuncTest
được gọi.
Result
được chỉ định.
Bây giờ, vì bước 1 đưa ra ngoại lệ, bước 2 không thực thi.
Nếu có bất cứ điều gì, tôi sẽ nói rằng hành vi bạn báo cáo từ các phiên bản trước đó không rõ ràng. Trong chức năng này:
function Test:integer;
begin
Result:=0;
try
Result:=FuncTest;
finally
ShowMessage(Result.ToString);
end;
end;
Tuyên bố Result:=FuncTest
đặt ra một ngoại lệ và vì vậy Result
không nên được sửa đổi bởi tuyên bố đó. Một cách khác để nghĩ về nó là hàm được gọi nhưng phép gán không được thực thi.
Một trong những vấn đề với ABI Delphi là các giá trị trả về hàm đôi khi được thực hiện như tham số ngụ ý var
. Điều đó có nghĩa là việc chuyển nhượng có thể hoặc không thể xảy ra. Để chứng minh:
{$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.
đầu ra này:
0
0
0
1
Đó là khá thất vọng. Không nên sửa đổi biến số của người gọi, nhưng việc sử dụng tham số ngụ ý var
thay vì trả về giá trị cho phép sự rò rỉ này. Theo quan điểm của tôi, đây là một lỗ hổng nghiêm trọng trong thiết kế của Delphi ABI, một lỗ hổng mà bạn sẽ không tìm thấy trong hầu hết các ngôn ngữ khác.
Trong mã của bạn, không có thông số var
vì loại trả về được chuyển vào sổ đăng ký. Trong trường hợp đó, bất kỳ phiên bản Delphi nào xuất ra 2
bị hỏng.
Về cơ bản, mã của bạn bị nhầm lẫn với kỳ vọng của nó. Nếu một hàm làm tăng một ngoại lệ thì bạn phải giả định rằng giá trị trả về là không xác định.
Cuối cùng, mã của bạn sẽ xuất ra 0
trong XE3 và XE7, vì vậy, tôi tự hỏi bạn cần đi bao xa để xem giá trị 2
.
Tôi không có phiên bản Delphi trước đó, nhưng tôi nghĩ đó là XE2, nơi trình biên dịch x64 được giới thiệu.A có một mã dựa trên thực tế là FuncTest trả về hoặc 1 (không thử khối) hoặc 2. Ok tôi đã nhận nó, không có nhiều chức năng nâng cao ngoại lệ, chỉ có thủ tục. – Molochnik
Sẽ tốt cho một chức năng để tăng ngoại lệ. Có gì sai khi mong đợi một giá trị được trả lại trong trường hợp đó. Trong trường hợp này, vì kiểu trả về phù hợp trong thanh ghi, ABI là tốt, không có các vấn đề param 'var'. Nhưng có, XE2 64 bit đã có một vài vấn đề tốt. –
Bạn có nghĩa là nếu hàm trả về e, g, một bản ghi thì sẽ không có vấn đề gì? – Molochnik