是这样的:
你新建一个Application,凡一个按钮,然后在里面写代码如下:
procedure TForm1.ButtonClick(Sender:TObject);
var
AButton:TButton;
begin
AButton.Free;
end;
运行之后,点击按钮,主窗体就会Free掉。但是程序还在运行!
你新建一个Application,凡一个按钮,然后在里面写代码如下:
procedure TForm1.ButtonClick(Sender:TObject);
var
AButton:TButton;
begin
AButton.Free;
end;
运行之后,点击按钮,主窗体就会Free掉。但是程序还在运行!
不知道abutton指向什么地方的情况下,调用free。这就是典型的c语言中wild pointer带来的不可预计的后果,delphi不应该对其负责。
在调用ButtonClick时,因为Delphi默认是FastCall调用,而ButtonClick为TForm1的方法,所以EAX即为Self值,
而一句AButton.Free,CPU窗口看到的就为Call TObject.Free
也就相当于Form1.Free,可以这样看
procedure TForm1.ButtonClick(Sender:TObject);
var
AButton:TButton;
begin
ShowMessage(AButton.Name);
end; 很有意思的阿
procedure TForm1.ButtonClick(Sender:TObject);
var
AButton:TButton;
begin
AButton.Caption := 'xzgyb';
ShowMessage(AButton.Name);
end;
如果在AButton.Free后加一ShowMessage(AButton.Name)则释放掉的是Button1, 当然这也会出错
都是编译器的东西,不懂
有时是Form1的引用,我想大家再追究 Button1,Form1的引用怎么恰好到了第一个
局部变量里面,就有点舍本逐末了。这不是bug,假如我用汇编 乱改TObject的VMT,程序出错,也能怪编译器不的是么
??
{$o-}
procedure TForm1.ButtonClick(Sender:TObject);
var
AButton:TButton;
begin
AButton.Free;
end;
{$o+}
大部分情况下会出错而默认被编译器优化了,就有一条AButton.Free;
编译器就不会在堆栈上递减ESP来产生一局部变量
而调用AButton.Free,用的EAX就是调用ButtonClick传过来的SELF
究其原因是因为,因为由于AButton没有被赋过值,一直是无效的,所以编译器会删除这个变量定义。这样就导致函数没有局部变量,也就没有了进入代码和退出代码。同时,AButton.Free也将会删除对AButton的引用,直接调用Free函数。而Free函数也是没有参数的,它只需要一个隐含的变量Self。而类成员函数调用默认都是把Self存放于EAX中。这样,调用OnClick时,Form被作为Self传入,而现在又被传入到Free函数中。因此会造成父窗口的Free。
如果在AButton前加一个对AButton读取的应用,就会迫使函数添加一段初始化代码,比如:
ShowMessage(IntToHex(Integer(AButton), 8));
这时候,AButton的位置正好相当于Sender,就可以把Button给Free掉。另外我这边用不优化方式编译,AButton正好为nil,因此不会有任何反应。
还有人要继续吗?
可以结贴了。
var
AButton: TButton;
BButton: TButton;
begin
AButton := BButton;
BButton.Free;
end;
BButton使用了两次,应该为它分配空间,而AButton只用了一次,应该是A无效,B有效。但实际上两个都被清除了。这是因为对于赋值语句,如果被赋值地变量在随后没有被引用,或立即又被赋值。这一个赋值语句会被删除,又只剩下BButton.Free了。
但是如果在AButton := BButton;换成:
AButton.Caption := '@#$%';
这下就相当于A对应Form,B对应Button了。原因也类似。
考虑下面两段代码效果也有点意思。 AButton.Caption := '@#$%';
BButton := AButton;
BButton.Free; AButton.Caption := '@#$%';
BButton := AButton;
BButton.Free;
你们都可以去看一看吗?我知道你们都是高手,不过,别笑可不可以?