从一个控件BUG想到的:如何判断类未被初始化!
type
pp1 = class
private
i: Tbutton;
end ;
........
........
........
procedure TForm1.Button1Click(Sender: TObject);
var pp2: pp1 ;
begin
if (pp2 <> nil) and (Assigned(pp2)) then // 因为这个判断不对!!!!!!!!!!!
begin
showmessage( 'Not nil ') ;
pp2.i := TButton.Create(Form1); // 这个建立在未知内存区,所以窗体关闭时,有AV内存溢出的错误
end ;
end;
不知道如何判断这个新类未被新建!
[解决办法]
从常规方法来讲应该是没有办法判断的。
一般用ASSIGNED来判断有个前提就是该对象在释放的时候是使用FreeAndNil来做才行,也就是要进行ps := nil;这个才能确保。
[解决办法]
偏题说一下:(个人看法,可能说得不对)
楼主的代码中有许多不够严谨的地方....
例如:在TForm1类里访问pp1类的私有成员;pp1类继承自TObject,却拥有一个TButton类的成员;var pp2: pp1 ;这句易令人误解。
[解决办法]
看...果然我说错了...
[解决办法]
呵!
那我言归正传给楼主讲一下,看楼主是否满意:
1、你不必用一个自定义类来试验的,你完全可以用一个普通的VCL类,例如一个TEdit
请比较一下:
代码一:
var
E : TEdit;
procedure TForm1.Button2Click(Sender: TObject);
begin
if not Assigned(E) then
begin
E := TEdit.Create(self);
E.Parent := self;
end;
end;
与
代码二:
procedure TForm1.Button2Click(Sender: TObject);
var
E : TEdit;
begin
if not Assigned(E) then
begin
E := TEdit.Create(self);
E.Parent := self;
end;
end;
运行之后,有何不同?
-------因为:局部指针变量不会被初始化为nil,只是被指向了一个随机的地址;而全局指针变量却被初始化为nil--------这就是为什么局部变量声明后立即用not Assigned(P)或 if P <> nil无效的原因!
2、pp2.i := TButton.Create(Form1); // 这个建立在未知内存区,所以窗体关闭时,有AV内存溢出的错误
这样用,本身就是不对的,原因我在二楼已说,现不多言。
[解决办法]
关于 1 ,多言一句:
一个程序占用的内存,大体可分为:代码区、全局数据区、堆、栈。
全局数据被application分配在“全局数据区”,并初始化它;
局部变量被动态地在“堆”内存分配,不初始化,而从堆里分配的内存,极可能是刚刚被释放的,仍保留着前面用过的数据......
[解决办法]
不要把Assigned(x)当宝!它只是判断 x是否为nil!
Tests for a nil (unassigned) pointer or procedural variable.
Unit
System
Category
miscellaneous routines
function Assigned(var P): Boolean;
Description
Use Assigned to determine whether the pointer or procedure referenced by P is nil.
[解决办法]
如果要判断一个对象变量是否被赋值,请一开始给这个变量初始化为 nil.
[解决办法]
顺便说一下,这里不存在什么BUG。如果你把这个看作BUG,那是你的BUG了。
[解决办法]
高人 学习了
[解决办法]
TButton.Create(Form1);
这个应该写成 TButton.Create(Self);
按钮在构造时候,指明物主为当前窗体,在窗体销毁时,会自动销毁该按钮。这个可以参阅 TComponent源代码.
------解决方案--------------------
jf~