type
  TMy=class
  private
    FValue:integer;
  public
    procedure MyTest;
    constructor Create(i:integer);
    destructor Destroy;override;
  end;
  PMy=^TMy;  TForm1 = class(TForm)
   ......
  public
    procedure My(var msg:TMessage);message WM_My;
  end;......{TMy}
constructor TMy.Create(i:integer);
begin
  inherited Create;
  FValue:=i;
  Form1.Memo1.Lines.Add('TMy.Create');
end;destructor TMy.Destroy;//override;
begin
  Form1.Memo1.Lines.Add('TMy.Destroy');
  inherited;
end;procedure TMy.MyTest;
begin
  Form1.Memo1.Lines.Add('TMy.MyTest - FValue : '+inttostr(FValue));
end;//************procedure TForm1.My(var msg:TMessage);
var pmy:PMy;
begin
  if msg.WParam=1 then
  begin
    pmy:=PMy(msg.LParam);
    pmy.MyTest;
  end;
end;procedure TForm1.Button15Click(Sender: TObject);
var my:TMy;
begin
  my:=TMy.Create(123);
  my.MyTest;
  PostMessage(handle,WM_My,1,integer(@my));
end;procedure TForm1.Button16Click(Sender: TObject);
var my:TMy;
begin
  my.MyTest;
end;procedure TForm1.Button17Click(Sender: TObject);
var my:TMy;
begin
  my:=TMy.Create(1);
  my.MyTest;
  my.Free;
end;按下 Button15 后,打印出信息 如下:
TMy.Create
TMy.MyTest - FValue : 123
TMy.MyTest - FValue : 123
按下 Button16 后,打印出信息 如下:TMy.MyTest - FValue : 14226404
按下 Button16 后,打印出信息 如下:
TMy.Create
TMy.MyTest - FValue : 1
TMy.Destroy
问题:
1、Button15 结束后,对象“my”有没有被释放掉?为什么不打印“TMy.Destroy”?为什么在 WM_My处理函数中,还能调用MyTest方法 且 打印 结果 正确??
2、为什么 Button16 按下后 ,没有创建对象就直接调用MyTest 却 没有报错,也打印出了信息??且既没有“TMy.Create”也没有“TMy.Destroy”被打印出来??如上 两点 中 5个问题,请解答,谢谢。

解决方案 »

  1.   

    上面 代码 中 消息处理函数错了,改为:procedure TForm1.My(var msg:TMessage);
    var p:PMy;//pmy 改为 p
    begin
      if msg.WParam=1 then
      begin
        p:=PMy(msg.LParam);
        p.MyTest;
      end;
    end;
      

  2.   

    为何,这样不行?如下:
    procedure TForm1.My(var msg:TMessage);
    var p:PMy;//pmy 改为 p
    begin
      if msg.WParam=1 then
      begin
        p:=PMy(msg.LParam);
        p.MyTest;
        p.free;      // 加了这句,但出错
      end;
    end;
      

  3.   

    老大,对象本来就是指针了,你没必要再定义一个对象的指针PMy=^TMy;因为这里p是对象的指针,所以
     p.free;      // 加了这句,但出错
    这样当然会出错,改成p^.free应该就没问题。建议先去学学指针之类的知识
      

  4.   

    你改成这样就行了:
    var p:TMy;
    begin
      if msg.WParam=1 then
      begin
        p:=PMy(msg.LParam)^;
        p.MyTest;
        p.Free;
      end;
    end;
      

  5.   

    对象已经是指针了,所以不要再声明一个PMy了,去掉你的PMy,再把这句
    PostMessage(handle,WM_My,1,integer(@my))
    改成
    PostMessage(handle,WM_My,1,integer(my))然后把WM_My消息处理函数改成这样:
    var p:TMy; 
    begin 
      if msg.WParam=1 then 
      begin 
        p:=TMy(msg.LParam); 
        p.MyTest; 
        p.Free; 
      end; 
    end; 
      

  6.   

    to wzwcn 
    多谢了,脑子一团乱。
    那个Button16,为什么只要“有函数就成”?能讲解讲解不?
      

  7.   

    Button16那样调竟然不出错我也不清楚原因,不过自己平时不要那样用就行了。记得对象一定要创建才能使用,使用完要释放掉就行了
      

  8.   

    DELPHI在能用寄存器时决不用堆栈
    所以button16那样的方式,可以成功,
    据我观察,在我的机器上,类似的变量可以定义两个,var my, my2:TMy;
    begin
      my.MyTest; //esi
      my2.MyTest;//edi
    end;
    //因为esi, edi里一般都是有值的,不会被判定为nil,cpu根据里边的值(希望没指向一个无法访问的地址啊),相对的根据位移,找到Finteger对应地址,取出值来,这样是说的过去的
    这样仍然行的通,但如果你再多定义一个,my3:Tmy,就不行了,寄存器不够用的了,这时就用到ebp-xx这样的堆栈值了,那时就AV了,因为堆栈上的事就不好说了
    另外,EBX寄存器可能让self偷偷的占去了
      

  9.   

    涉及到Delphi的对象模型。
    像这种调用,一般是直接调用这个函数,把对象当做隐含参数传递给函数,你没有用到对象里的数据,当然不出错。
      

  10.   

    不是碰巧,他那个函数不用到对象里的数据,也不用到vtable,所以不出错。
    delphi在这种情况下的调用纯粹就是静态调用而已。
      

  11.   

    不干寄存器的事,delphi对这种函数的调用就是静态调用,my.MyTest等于是MyTest(my)。
      

  12.   

    这什么意思?我不是用到了 
    private
        FValue:integer;
    的吗?
      

  13.   

    关于寄存器的结论,我是看单步跟踪时,看CPU的DebugWindows得出的结论,当然,在其它人的机器上可能表现不一样,但我认为道理可能就是这样的,
    并不是我想当然的说说而已
    另外,大富翁论坛的这个帖子似乎分析的更详细
    http://www.delphibbs.com/keylife/iblog_show.asp?xid=31260
      

  14.   

    "不干寄存器的事,delphi对这种函数的调用就是静态调用,my.MyTest等于是MyTest(my)。"
    如果这个成立,你试过多声明几个局部变量没有?在我的机器上,第三个未create的局部变量作MyTest操作时就会出av错误,前两个怎么也不会出错
      

  15.   

    看错了,是因为指针未赋值时一般为NULL,不会指向未知空间。
      

  16.   

    我写了个这个:
    procedure TForm1.Button19Click(Sender: TObject);
    var i:integer;
        my:TMy;
    begin
      if my=nil then
        memo1.Lines.Add('nil')
      else
        memo1.Lines.Add('<> nil');
      memo1.Lines.Add('integer(My) : '+inttostr(integer(My)));
      My.MyTest;
      copymemory(@i,pointer(integer(My)+sizeof(pointer)),sizeof(integer));
      memo1.Lines.Add('i : '+inttostr(i));
    end;
    打印出来时这样:
    <> nil
    integer(My) : 4388748
    TMy.MyTest - FValue : -217126717
    i : -217126717
    说明啥不?