发现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,也不会报错。

解决方案 »

  1.   

    我用D2009测试也有这个问题,但是用XE测试会报错!
      

  2.   

    ShowMessage(Obj.Caption);是显示对话框,语法没错误,不会报错
      

  3.   

    编译器的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;
      

  4.   

    奇怪的是下面代码还是不会出错:
    procedure TForm1.Button1Click(Sender: TObject);
    var
      Obj: TLabel;
    begin
      Obj.Caption := 'AAA';
      Button1.Caption:='BBB';
      //ShowMessage(Obj.Caption);
    end;
    而且TForm1的caption会变成AAA
      

  5.   

    顶楼上的,确实是这样的。而且,正如1楼说的,这个BUG在D2009下依然存在。
      

  6.   

    顶楼上的。楼上的代码不会报错。而且1楼说D2009下这个BUG依然存在,不过我没有验证。
      

  7.   

    顶楼上的。楼上的代码不会报错。而且1楼说D2009下这个BUG依然存在,不过我没有验证。
      

  8.   

    我之前已经说了,单步跟踪到Controls单元,你就明白了。
      

  9.   

    在procedure TForm1.Button1Click(Sender: TObject);之前加上{$O-}运行就会报错了
      

  10.   

    这种事情在C++Builder中是不会出现的。如果声明了一个对象但没有初始化就访问其成员,直接就AV鸟。
      

  11.   

    编译指令{$O-}的意思是关掉编译优化(Optimizations)
      

  12.   

    改成这样,应该报错了吧,可是还不报错procedure TForm1.Button1Click(Sender: TObject);
    var
      Obj: TLabel;
    begin
      Obj := nil;    //新增加的
      Obj.Caption := 'AAA';
      ShowMessage(Obj.Caption);
    end;
    这样执行就更有意思了,Button1的caption没有编号,弹出的对话框中是空白的。
      

  13.   


    加上后,这样写会报错:
    procedure TForm1.Button1Click(Sender: TObject);
    var
      Obj: TLabel;
    begin
    //  Obj := nil;
      Obj.Caption := 'AAA';
      ShowMessage(Obj.Caption);
    end;
    如果把Obj := nil开放出来不报错,D6 下测试。
      

  14.   

    无聊不无聊,Delphi又不会对局部变量初始化,obj的值是个随机的,你怎么知道他一定没有指向一个正常值。
    试试这样吧:
    var
      obj: TLabel;
    begin
      ShowMessage(IntToStr(DWORD(obj)));
    end;
      

  15.   

    加上Self限定就会出现想要的错误:procedure TForm1.Button1Click(Sender: TObject);
    var
      Obj22: TLabel;
    begin
      Self.Obj22.Caption := 'AAA';
    end;
      

  16.   

    你在 XE UPDATA1下面试试,准报错。
      

  17.   

    路过观望下  楼上的大牛都解释了啊。  应该这个 obj  分配到了 form1 的地址了吧。。
      

  18.   

    我来解释一下:
    1 delphi不会初始化局部变量,指向的地址是未知的,虽然可以调用他的熟悉或方法但是结果是不可预测的。
    2 第一行,加了 obj := nil以后,因为编译器的优化,编译器认为这一句没有意义,所以不会编译,跟没加一样,取消编译器优化,obj := nil就有效果了,他指向空地址,再对其调用就肯定报错了。可以试一下,讲obj声明为类的成员而不是局部变量,就会报错了,因为对于类成员,delphi会对他默认初始化为nil
      

  19.   

    好久不用了。obj 不是内部变量吗?换个名字试试看? 比如ooojb 还出这样的问题吗?