发现Delphi下一个很诡异的地方

xmfan2000 2011-10-19 05:37:10
发现Delphi下一个很诡异的地方,大家看看能不能重现,本人使用D6和D7都出现了这个问题:
新建一个窗体,上面放一个按钮,然后在其 OnClick 事件中填写:


procedure TForm1.Button1Click(Sender: TObject);
var
Obj: TLabel;
begin
Obj.Caption := 'AAA';
ShowMessage(Obj.Caption);
end;


这里,我声明了一个obj变量,并没有创建它,点这个按钮后,按钮标题改成了AAA,并不会报错。

如果把ShowMessage这句去掉,变成这样:


procedure TForm1.Button1Click(Sender: TObject);
var
Obj: TLabel;
begin
Obj.Caption := 'AAA';
// ShowMessage(Obj.Caption);
end;


点这个按钮后,窗体的标题改成了AAA,也不会报错。
...全文
1604 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
还是江筱吧 2011-10-25
  • 打赏
  • 举报
回复
跟名字没关系
lyhoo163 2011-10-24
  • 打赏
  • 举报
回复
路过。
huiyue99 2011-10-24
  • 打赏
  • 举报
回复
好久不用了。obj 不是内部变量吗?换个名字试试看? 比如ooojb 还出这样的问题吗?
「已注销」 2011-10-24
  • 打赏
  • 举报
回复
我来解释一下:
1 delphi不会初始化局部变量,指向的地址是未知的,虽然可以调用他的熟悉或方法但是结果是不可预测的。
2 第一行,加了 obj := nil以后,因为编译器的优化,编译器认为这一句没有意义,所以不会编译,跟没加一样,取消编译器优化,obj := nil就有效果了,他指向空地址,再对其调用就肯定报错了。

可以试一下,讲obj声明为类的成员而不是局部变量,就会报错了,因为对于类成员,delphi会对他默认初始化为nil
jiangzs188136923 2011-10-23
  • 打赏
  • 举报
回复
你在 XE UPDATA1下面试试,准报错。
爱蹄子的羊头 2011-10-23
  • 打赏
  • 举报
回复
路过观望下 楼上的大牛都解释了啊。 应该这个 obj 分配到了 form1 的地址了吧。。
yushf 2011-10-22
  • 打赏
  • 举报
回复
无聊不无聊,Delphi又不会对局部变量初始化,obj的值是个随机的,你怎么知道他一定没有指向一个正常值。
试试这样吧:
var
obj: TLabel;
begin
ShowMessage(IntToStr(DWORD(obj)));
end;
BlueStorm 2011-10-22
  • 打赏
  • 举报
回复
虽然没报错,但报了警告,应该还算OK啦。
SailorXing 2011-10-22
  • 打赏
  • 举报
回复
加上Self限定就会出现想要的错误:

procedure TForm1.Button1Click(Sender: TObject);
var
Obj22: TLabel;
begin
Self.Obj22.Caption := 'AAA';
end;

iqyely 2011-10-21
  • 打赏
  • 举报
回复
来关注下,还真没在意过
diecode 2011-10-21
  • 打赏
  • 举报
回复
这个不能算BUG吧
22222bbb 2011-10-20
  • 打赏
  • 举报
回复
试了delphi2007同样是这样。。
仙侣步惊云 2011-10-20
  • 打赏
  • 举报
回复
奇怪的是下面代码还是不会出错:
procedure TForm1.Button1Click(Sender: TObject);
var
Obj: TLabel;
begin
Obj.Caption := 'AAA';
Button1.Caption:='BBB';
//ShowMessage(Obj.Caption);
end;
而且TForm1的caption会变成AAA
亮剑_ 2011-10-20
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 s11ss 的回复:]
在procedure TForm1.Button1Click(Sender: TObject);之前加上{$O-}运行就会报错了
[/Quote]
编译指令{$O-}的意思是关掉编译优化(Optimizations)
D_Parent 2011-10-20
  • 打赏
  • 举报
回复
编译器的bug而已。当对一个标签类设置时,调用了Controls单元的SetText方法,而该方法并不需要具体的对象就会执行SetTextBuf(PChar(Value)),因而在内存保存了“AAA”,你点击按钮时,按钮的标签就被设置为“AAA”了,这是因为Obj未建立,编译器把Button1当做它了。
把你的代码改为这样,编译器就能发觉错误了:
procedure TForm1.Button1Click(Sender: TObject);
var
Obj: TLabel;
begin
Obj.Caption := 'AAA';
Button1.Caption:='BBB';
ShowMessage(Obj.Caption);
end;
ccrun.com 2011-10-20
  • 打赏
  • 举报
回复
这种事情在C++Builder中是不会出现的。如果声明了一个对象但没有初始化就访问其成员,直接就AV鸟。
s11ss 2011-10-20
  • 打赏
  • 举报
回复
在procedure TForm1.Button1Click(Sender: TObject);之前加上{$O-}运行就会报错了
D_Parent 2011-10-20
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 sxqwhxq 的回复:]
奇怪的是下面代码还是不会出错:
procedure TForm1.Button1Click(Sender: TObject);
var
Obj: TLabel;
begin
Obj.Caption := 'AAA';
Button1.Caption:='BBB';
//ShowMessage(Obj.Caption);
end;
而且TForm1的caption会……
[/Quote]
我之前已经说了,单步跟踪到Controls单元,你就明白了。
wzwcn 2011-10-20
  • 打赏
  • 举报
回复
与BUG无关
wzwcn 2011-10-20
  • 打赏
  • 举报
回复
很正常,像使用已经释放的指针一样,有时也不会报错,但结果是不可预见的。
加载更多回复(13)

5,386

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧