gpt4 book ai didi

Delphi 5编译器错误返回接口(interface)指针而不是返回值

转载 作者:行者123 更新时间:2023-12-03 18:30:57 24 4
gpt4 key购买 nike

我向您展示了 Delphi 5 编译器中的一个错误。我知道不会有任何解决办法。但解决方法是 super

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.

真正的胆量是函数 做事 应该返回一个:
function DoStuff(): Integer;
var
foo: IFoo;
begin
foo := TFoo.Create;
try
Result := 1;
Exit;
finally
foo.Grob(0, 0);
end;

Result := 2;
end;

该函数应返回 一个 .相反,它返回接口(interface)对象的地址:

enter image description here

大会

代码实际上确实开始将结果设置为 1:

Project1.dpr.30:结果:= 1;
移动 ebx,$00000001 ;将返回值 1 放入 EBX
Project1.dpr.31:退出;
调用 @TryFinallyExit ;调用 finally block
jmp DoStuff + $6E

并且当函数即将返回时,它确实将 EBX 复制到 EAX 中以返回它:

mov eax,ebx ;EBX 到 EAX 中返回

但是 finally block (调用接口(interface)方法)是问题所在。它吹走存储在 EBX 中的返回值:

我们从 到达这里调用@TryFinallyExit
Project1.dpr.33: foo.Grob(0, 0);
异或 ecx,ecx
异或 edx,edx
mov eax,[ebp-$04]
mov ebx,[eax] <----- 用接口(interface)地址覆盖 ebx
调用 dword ptr [ebx+$0c]
ret

在对 finally block 的“调用”之后,它返回到跳转,将其发送到:

Project1.dpr.36:结果:= 2;
...
xor eax,eax
流行音乐
流行音乐
流行音乐
mov fs:[eax],edx
推 $00442e1f
lea eax,[ebp-$04]
调用@IntfClear
ret
...
mov eax,ebx <----- 将覆盖的 EBX 放入 EAX 以返回
Project1.dpr.37:结束;

流行音乐
流行音乐
流行音乐
ret

返回值不是一或二,而是接口(interface)指针的地址。

我知道你们都没有 Delphi 5。即使你有,

"What would you like me to say?"



我知道困难。我真正需要的是某种解决方法。

最佳答案

如您所见,编译器将结果存储到 EBX , 但在随后复制 EBX 之前覆盖它进入 EAX将结果返回给调用者。

编译器应该执行以下操作之一:

  • 使用不同的寄存器临时存储结果值,使其使用EBX不破坏结果值,或
  • 不使用 EBX在调用 Grob , 或
  • 将结果值存储在比寄存器更持久的东西中,例如堆栈中。

  • 显然,选项 1 和 2 对您来说并不容易,但后者是您需要在此示例中实现的解决方法 - 使用局部变量来保存您想要的 Result值(value),直到您准备好返回它:
    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;

    关于Delphi 5编译器错误返回接口(interface)指针而不是返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32529922/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com