罕事!一个创建的资源不能被释放。 ( 积分: 5 )

  • 主题发起人 主题发起人 青云
  • 开始时间 开始时间

青云

Unregistered / Unconfirmed
GUEST, unregistred user!
我做了一个控件,

控件里动态创建了一个 FPanel;

在控件的 onCreate 事件里设置
FPanel:=TPanel.Create(nil);

在控件的 onDestroy 事件里设置

if Assigned(FPanel) then
FreeAndNil(FPanel);

结果控件所在窗体关闭的时候就报错。
原因是 FreeAndNil(FPanel); 这句话导致的。

我就纳闷:
这样控制好了,系统好像不应该报错吧:

if Assigned(FPanel) then
FreeAndNil(FPanel);

因为 如果能够确认 Assigned(FPanel) =true
那么就必然可以执行 FreeAndNil(FPanel);

难道这种写法存在危险?

真不知道怎样写才安全。
 
我做了一个控件,

控件里动态创建了一个 FPanel;

在控件的 onCreate 事件里设置
FPanel:=TPanel.Create(nil);

在控件的 onDestroy 事件里设置

if Assigned(FPanel) then
FreeAndNil(FPanel);

结果控件所在窗体关闭的时候就报错。
原因是 FreeAndNil(FPanel); 这句话导致的。

我就纳闷:
这样控制好了,系统好像不应该报错吧:

if Assigned(FPanel) then
FreeAndNil(FPanel);

因为 如果能够确认 Assigned(FPanel) =true
那么就必然可以执行 FreeAndNil(FPanel);

难道这种写法存在危险?

真不知道怎样写才安全。
 
给分~ 作者: jeanler (jeanler) ▲△△△△ 男的普通会员 编辑删除
2005-11-30 10:01:43
用个比喻把~(某个大虾说得),房子被拆了,但门牌号还在~
我在盒子上已经回答你了。Assigned适用于指针的测试,不适合于类实例存在的测试
 
如果在释放的时候出现指针错误,应该是其已经被释放过了。
 
要不在destroy 事件里就不写下面这个:

if Assigned(FPanel) then
FreeAndNil(FPanel);

不知道这样会不会浪费内存?
 
我做了一个控件,

控件里动态创建了一个 FPanel;

在控件的 onCreate 事件里设置
[red]FPanel:=TPanel.Create(Self); // 注意这里,让你的控件成为这个TPanel的所有者[/red]

在控件的 onDestroy 事件里设置

[red] //if Assigned(FPanel) then // 没必要管它了,所有者(你的控件)负责释放
//FreeAndNil(FPanel);[/red]
 
多谢 特尔斐 朋友:
其实 我创建是尝试很很多
比如: FPanel:=TPanel.Create(Self);
FPanel:=TPanel.Create(Tform);
FPanel:=TPanel.Create(nil);

我都尝试过,不知道在destroy里不写释放,系统的内存是不是会被浪费掉了。
 
自己看看FreeAndNil的源码就知道了~ 不浪费内存的。
 
多谢 特尔斐 朋友:
其实 我创建是尝试很很多
比如: FPanel:=TPanel.Create(Self);
FPanel:=TPanel.Create(Tform);
FPanel:=TPanel.Create(nil);

我都尝试过,不知道在destroy里不写释放,系统的内存是不是会被浪费掉了。

无论你是怎样创建,主程序退出时,所有的内存就都释放了。不过对于主程序不断调用(你写的控件如果没有释放)创建,释放的话,内存会不断增加,所以一定要释放,释放的原则就是谁创建谁释放。
 
我做了一个控件,

控件里动态创建了一个 FPanel;

在控件的 onCreate 事件里设置
FPanel:=TPanel.Create(nil);

在控件的 onDestroy 事件里设置

还有就是你做的这个控件在事件里创建和释放类的私有成员是不对的,应该在构造和析构中才对
public
Constructor Create(AOwner: TComponent); override;
destructor Destroy; override;

constructor xxx.Create(AOwner: TComponent);
begin
inherited;
FPanel:=TPanel.Create(nil);
end;
destructor xxx.Destroy;
begin
FPanel.free;
inherited;
end;
 
可能是释放已经释放的控件.
 
if Assigned(FPanel) then
FreeAndNil(FPanel);
要放在inherited的前面.
或者你覆盖BeforeDestruction这个方法.
 

Similar threads

后退
顶部