Delphi 5编译器错误返回接口指针而不是返回值
我向你展示了Delphi 5编译器中的一个错误。 我知道这不会有任何解决办法。 但是一个解决方法是超级的
program Project1;
uses
Dialogs, SysUtils;
{$R *.RES}
type
IFoo = interface
['{D68DA49A-F870-433D-9343-4964BFECFF27}']
procedure Grob(a: Integer; b: Integer);
end;
TFoo = class(TInterfacedObject, IFoo)
public
procedure Grob(a: Integer; b: Integer); virtual;
end;
procedure TFoo.Grob(a: Integer; b: Integer);
begin
end;
function DoStuff(): Integer;
var
foo: IFoo;
begin
foo := TFoo.Create;
try
Result := 1;
Exit;
finally
foo.Grob(0, 0);
end;
Result := 2;
end;
var
n: Integer;
begin
n := DoStuff;
if n <> 0 then
ShowMessage('Failed: '+IntToStr(n))
else
ShowMessage('Passed: '+IntToStr(n));
end.
真正的胆量是DoStuff函数,它应该返回一个:
function DoStuff(): Integer;
var
foo: IFoo;
begin
foo := TFoo.Create;
try
Result := 1;
Exit;
finally
foo.Grob(0, 0);
end;
Result := 2;
end;
该函数应该返回一个 。 相反,它会返回接口对象的地址:
大会
代码实际上开始将结果设置为1:
Project1.dpr.30: Result := 1; mov ebx,$00000001 ; place return value 1 in EBX Project1.dpr.31: Exit; call @TryFinallyExit ; call the finally block jmp DoStuff + $6E
并且随着函数即将返回,它将EBX复制到EAX中以返回它:
mov eax,ebx ;EBX into EAX for return
但最后阻止(调用接口方法)是问题。 它吹走了存储在EBX中的返回值:
We arrive here from the call @TryFinallyExit Project1.dpr.33: foo.Grob(0, 0); xor ecx,ecx xor edx,edx mov eax,[ebp-$04] mov ebx,[eax] <----- overwriting ebx with interface address call dword ptr [ebx+$0c] ret
在对finally块的“调用”之后,它返回到一个跳转,它将它发送到:
Project1.dpr.36: Result := 2; ... xor eax,eax pop edx pop ecx pop ecx mov fs:[eax],edx push $00442e1f lea eax,[ebp-$04] call @IntfClear ret ... mov eax,ebx <----- places overwritten EBX into EAX for return Project1.dpr.37: end; pop ebx pop ecx pop ebp ret
返回值而不是一个或两个是接口指针的地址。
我知道你们中没有一个有Delphi 5,即使你做到了,
“你想让我说什么?”
我知道困难。 我真正需要的是某种解决方法。
正如您观察到的那样,编译器将结果存储到EBX
,但在随后将EBX
复制到EAX
以将结果返回给调用方之前,将其覆盖。
编译器应该执行以下操作之一:
EBX
不会破坏结果值,或 Grob
不使用EBX
,或者 很显然,选项1和选项2并不适合您,但后者是您需要在此示例中实现的解决方法 - 使用局部变量来保存您的预期Result
值,直到您准备好返回它:
function DoStuff(): Integer;
var
foo: IFoo;
MyResult: Integer;
begin
foo := TFoo.Create;
try
try
MyResult := 1;
Exit;
finally
foo.Grob(0, 0);
end;
MyResult := 2;
finally
Result := MyResult;
end;
end;
链接地址: http://www.djcxy.com/p/89891.html
上一篇: Delphi 5 compiler bug returning interface pointer rather than return value
下一篇: How to get address of Delphi code label in another function?