I rewrite old code (x86 ~ 1998 year, delphi 7) on new standart (x64, Rad Studio XE 10.4). I find problem place, which stopped my work. I create minimum example, that you can debugging (The structure of the code is strictly like this!):
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.
On Form there is button, pressed on which on screen will be write message like: Caption button.
This code working without error on x86 platform, but broken on x64 platform. I look in debugger, stack trace and dissassembler (x64 platfrom!) and find error: when app call callback procedure IntNextVis(btn: TButton; i: Integer);
, then in asm code args callback first transmitted, and than remove! Therefore, call ShowMessage(btn.Caption);
is an not correct, as btn will be removed. My current configuration Debug
.
Why that going on and how fix this bug?
P.S.: please, tell me solution this problem without move procedure IntNextVis
of local area of visibility from global area of visiblity, as in my old code very very very mach such codes.