首页 > 解决方案 > 使用回调访问 voilation delphi x64

问题描述

我在新标准(x64,Rad Studio XE 10.4)上重写了旧代码(x86 ~ 1998 年,delphi 7)。我找到了问题的地方,这停止了我的工作。我创建了一个最小的例子,你可以调试(代码的结构严格来说是这样的!):

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, ShellApi;

type
TTestProc = procedure(btn: TButton; i: Integer);

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);

    procedure KeyDownTest();
    function FindNewFocused(): boolean;
    procedure Iterate(IterateProc: TTestProc);

  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


procedure TForm1.Button1Click(Sender: TObject);
begin
  KeyDownTest();    // -->  KeyDownTest
end;

procedure TForm1.KeyDownTest();
begin
  FindNewFocused();  // -->  FindNewFocused
end;

function TForm1.FindNewFocused(): boolean;

  procedure IntNextVis(btn: TButton; i: Integer);
  begin
    ShowMessage(btn.Caption);  // ----> ERROR: ACCESS VOILATION!
  end;

begin
  Iterate(@IntNextVis); // -->  Iterate
  Result := True;
end;

procedure TForm1.Iterate(IterateProc: TTestProc);

  procedure IntIterate(btn: TButton; i: Integer);
  begin
      if(i > 2) then
        Exit;       // --> break reqursive
      if(i = 2) then
        IterateProc(btn, i) // -->  FindNewFocused.IntNextVis
      else
        IntIterate(btn, i + 1); // -->  Iterate.IntIterate
  end;

var
  i: Integer;
begin
    i := 0;
    //ShowMessage(Button1.Caption); // ----> WORKING!
    IntIterate(Button1, i);  // -->  Iterate.IntIterate
end;
end.

在表格上有一个按钮,按下该按钮在屏幕上将写下消息,例如:标题按钮。此代码在 x86 平台上正常工作,但在 x64 平台上损坏。我查看调试器、堆栈跟踪和反汇编程序(x64 平台!)并发现错误:当应用程序调用回调过程时IntNextVis(btn: TButton; i: Integer);,然后在 asm 代码中首先传输 args 回调,然后删除!因此, callShowMessage(btn.Caption);是不正确的,因为 btn 将被删除。我目前的配置Debug。为什么会这样以及如何修复这个错误?PS:请告诉我在不IntNextVis从全局可见性区域移动局部可见性区域的程序的情况下解决这个问题,就像在我的旧代码中非常非常非常马赫这样的代码一样。

标签: delphi

解决方案


推荐阅读