gpt4 book ai didi

Delphi XE4 - 在 DLL 中动态创建表单导致 AV

转载 作者:行者123 更新时间:2023-12-01 17:35:10 24 4
gpt4 key购买 nike

我的主应用程序中加载了一个 DLL 应用程序。DLL 包含在运行时创建的表单。其功能是:在主应用程序中,我有一个菜单,只要按下该菜单,就会从 DLL 中调用一个过程。此过程动态创建表单。

procedure doCreateForm;
var
myForm: TForm1;
begin
myForm := TForm1.Create(nil)
try
...
except
myForm.Free;
end;
end;

结账程序:

procedure CloseWindow(ASender: TForm1);
begin
FreeAndNil(ASender);
Application.ProcessMessages;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
CloseWindow(Self);
end;

该问题(访问冲突)仅在第二次尝试创建表单时发生。不是第一次,不是第三次、第四次、第五次等等。

所以我单击菜单,表单被创建(动态)并关闭(如果在表单创建事件期间不满足条件)。我再次单击菜单,当调用 myForm.Create(nil) 时,AV 升高。我再次点击菜单,一切正常。我一次又一次地点击,一切正常。只有当第二次按下时,AV 才会升高。DLL中动态创建可 window 体有问题吗?

更详细的解释:

链条是:

  1. 我创建 MyForm (myForm := TForm1.Create(nil))

  2. 在展示表格之前,我会进行一些条件测试。

  3. 如果一切正常,myForm.Show - 工作正常,我也可以正确关闭 myForm

  4. 如果出现问题:

a).我创建了一个消息表单 myMessageForm := TMyMessageForm.Create(nil),其中包含一个关闭计时器(表单在 10 秒后关闭)。此表单在 onClose 事件中有 action:=caFree

b).我调用 myForm.Close。此表单在 onClose 事件中还有 action:=caFree - 此表单在 myMessageForm 关闭之前关闭(由于 myMessageForm 中存在计时器)

这两种形式都是以零所有者创建的,但它们以某种方式连接(我不知道为什么)。并且表格的销毁未正确执行。下次调用 myForm.Create(nil) 或 myMessageForm.Create(nil) 时,会发生访问冲突。myMessageForm 应该独立于 myForm 创建,并且它的销毁不应以任何方式影响 myForm 的销毁。

unit1;

procedure doCreateForm;
var
myForm: TForm1;
begin
myForm := TForm1.Create(nil)
try
with myForm do
begin
if <test condition true> then Show
else
begin
ShowErrMessage('Error', 'Error message text', errType);
Close;
end;
end;
except
myForm.Free;
end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;



unit2;

procedure ShowErrMessage(title, text: string; err: mtErrType);
var
myMessageForm: TMyMessageForm;
begin
myMessageForm := TMyMessageForm.Create(nil)
try
with myMessageForm do
begin
StepDownCounter := 10;
CloseTimer.Enable := True;
end;
except
myMessageForm.Free;
end;
end;

procedure TMyMessageForm.CloseTimerTimer(Sender: TObject);
begin
StepDownCounter := StepDownCounter - 1;
if (StepDownCounter < 1) then
begin
CloseTimer.Enabled := False;
LabelStepDownText.Visible := False;
Close;
end
else
begin
LabelStepDownText.Caption := 'Window will close in ' + IntToStr(StepDownCounter) + 's';
LabelStepDownText.Visible := True;
end;
end;

procedure TMyMessageForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;

最佳答案

您正在销毁正在执行当前方法的对象。该对象被销毁后执行的所有代码都是无效的。

您应该将关闭操作设置为caFree,或使用Release,如前所述。它们的工作原理是向队列发送一条消息,以允许在当前方法返回后销毁对象。您可以通过调用ProcessMessages来泵送队列来颠覆这一点。删除对 ProcessMessages 的调用。

关于Delphi XE4 - 在 DLL 中动态创建表单导致 AV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22791035/

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