类的释放问题:类释放了为什么总是出错。(这个问题困扰我很久了,请各位大虾不吝赐教) (200分)

  • 主题发起人 主题发起人 troyliu
  • 开始时间 开始时间
T

troyliu

Unregistered / Unconfirmed
GUEST, unregistred user!
我的类是一个动态建立的,但是当我点击image时(也就是关闭这个对象)为什么出错。(大部分时间没有)
大概是10次到20次出现一次;请教高手。

错误信息如下:
---------------------------
Debugger Exception Notification
---------------------------
Project tt.exe raised exception class EAbstractError with message 'Abstract Error'. Process stopped. Use Step or Run to continue.
---------------------------
OK Help
---------------------------

unit Main;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;

type
TMyPanel = class(TPanel)
FMined: TImage;
FClose: TImage;
Private
procedure MinedClick(Sender: TObject);
public
constructor Create(AOwner: Tcomponent);override;
destructor Destroy;override;
end;

TForm1 = class(TForm)
Button1: TButton;
Image1: TImage;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
MyPanel: TMyPanel;
implementation

{$R *.dfm}

constructor TMyPanel.Create(AOwner: Tcomponent);
begin
inherited Create(AOwner);

FMined := TImage.Create(self);
FMined.Parent := self;
FMined.Left := 10;
Fmined.Top := 10;
FMined.Height := 10;
FMined.Width := 10;
Fmined.AutoSize := True;
FMined.Picture := TForm1(Owner).Image1.Picture;
FMined.OnClick := MinedClick;
end;

destructor TMyPanel.Destroy;
begin
inherited Destroy;
end;

procedure TMyPanel.MinedClick(Sender: TObject);
begin
Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
MyPanel := TMyPanel.Create(self);
MyPanel.Parent := Form1;
MyPanel.Top := 21;
MyPanel.Left := 21;
MyPanel.Height := 50;
MyPanel.Width := 90;
end;
 
写法不对。看看d6 那个 什么组合控件的vcl
 
Destroy中未将 FMined 释放掉!!
 
to Destroy中未将 FMined 释放掉!!
这个更不对,类释放的时候是自动释放它的子类的。不然每次都出错。
象Form1你只管主窗体释放,它包含的子类也都释放了。不用手动释放的
to 人在昆明
请指明我哪里不对。
我只是创建一个自己用的类,不是创建自定义组件。
 
这种写法有问题,图片不一定能正常显示。。。
 
to 张无忌,这样对吗。
FMined := TImage.Create(self);
FMined.Parent := self;
FMined.Left := 10;
Fmined.Top := 10;
// FMined.Height := 10;
// FMined.Width := 10;
Fmined.AutoSize := True;
FMined.Picture := TForm1(Owner).Image1.Picture;
FMined.OnClick := MinedClick;
 
这个问题困扰我很久了,请各位大虾不吝赐教。
 
不能在类中的事件中释放自己。
分析你的流程:当执行MinedClick的时候,是在类自身中,释放了自己
当MineClick返回时(事件执行完毕要返回吧?),已经找不到本身了,
所以会报这种错误。
解决办法:被动释放即可。
ps:许久不写Delphi了,如果分析有误,请各位多加指教。
 
to sun77wind
照你的解释应该是每次都出错吧,可是我的情况确实10-20次才报错。
哪为什么只是偶然报错
 
我的却是每次都报错?!
另外,有谁见到过在类中释放自己的例子,我没有印象
 
估计是你的鼠标点得太快的原因。[:)]
一下子生成了好几个TMyPanel
 
可能楼主说的也有道理,我还没真正将控件的创建过程搞明白!
但TPANEL的父类到底有没有实现INSERTCOMPONENT方法我也不能很确定!如果他未将控件
加入到TLIST中的话那怎么去析构他的子类!
还有就是TPANEL的析构有没将所属的TLIST中所指象的对象析构我现在也不能确定!
所以我认为比较保险的做法就是在你的控件的析构函数中将那两个控件显式的析构掉!

 
同意ReallyFail的说法:

> 来自:ReallyFail, 时间:2003-3-19 10:45:00, ID:1693792
> Destroy中未将 FMined 释放掉!!

我不认为类释放的时候自动释放它的子类。不释放子类不会每次都出错,不信楼主您可以
声明一个全局对象,退出的时候别释放,看看会不会出错。
而Form1,你所说的它包含的子类则指的是你用鼠标拖下来的各种控件吧,如果你自己在
TForm1中自己申明一个子类,我不认为他可以自动释放。如果你有兴趣,我这儿有一个实
验,如果你要求,我会将源代码贴出来的。
 
不能在自己的事件中释放自己,否则就有可能报错
这是Borland的文档中明确说明的。
其他代码不变,改成在Form1中释放:
procedure TMyPanel.MinedClick(Sender: TObject);
begin
//不在这里Free自己,而是给OWNER发一个消息,让OWNER来释放自己
PostMessage(TForm(Owner).Handle, WM_USER, Integer(Self), 0);
end;

TForm1 = class(TForm)
...
private
procedure FreeIt(var Msg: TMessage); message WM_USER;
...

procedure TForm1.FreeIt(var Msg: TMessage);
begin
TMyPanel(Msg.WParam).Free;
end;

这样的话随便你怎么点都不会出错。
所以可以知道,出错的原因就是由于在自己的事件中把自己Free了。
 
類最好不要Free自己
另外 FMined free時會把
TForm1(Owner).Image1 的 Picture 也 Free掉
看看是不是 FMined free 後,你又調用了 TForm1(Owner).Image1 的 Picture

 
>>FMined.Picture := TForm1(Owner).Image1.Picture;
注意这里的 Picture 的类型,我试过:
Ico 的出错
Jpg 的是好的,
希望对楼主有帮助:)
 
看了一下你的代码:
1.TMyPanel.Destroy写的有问题.你在create中创建了新的东西,那么在释放的时候,应该先释放
你创建的东西,比如image,然后调用inherited。
2。不应该自己释放自己,这样做很危险。你可以在他的上一层释放自己。比如TForm中,另外你
需要的时候你可以触发一个时间,在另外的响应这个事件的时候释放这个类。比如在
procedure TMyPanel.MinedClick(Sender: TObject);中触发一个自定义事件。

 
噢,感谢各位的参与和帮助。
我总结了一下,你们指出我的错误主要是两个:
1.不要释放自己创建的子类。
在下不这么认为。如果在Destroy中释放自己的子类,或者在其他地方释放,
然后调用Free,这样每次都发生错误。象Panel它是自动释放自己的子类的。
2.不要自己释放自己,否则返回时出现内存错误。
我现在还是不明白为什么有时出错,有时就不出错。
不过我在外部调用(或者用消息),这样就没有错误了。
3.to dreamfly1024
我试了一下,真的是ico的有问题,jpg的就没有问题。
这下我可就真的更糊涂了。哎呀,Delphi的问题?还是我的问题。
惨了!!!
 
to ASCII
你也可是试试我的这个源码,的确是不用释放子类的。
你的实验还是发送到我的邮箱吧
liut@efidic.com
 
后退
顶部