风之谷
点亮心灵,基础补习中...

导航

<2012年2月>
2930311234
567891011
12131415161718
19202122232425
26272829123
45678910

统计
  • 随笔 - 15
  • 文章 - 1
  • 评论 - 35
  • 跟踪 - 0

公告
  • 有事点这里

文章分类

档案

随笔分类

相册

好友博客

技术站点

登录
    帐号
    密码
    记住我:
     
 

看了一下午的《Delphi对象模型》有一个问题:

A := TA.Create;在内存中创建的对象的头4个字节到底指向哪?
在《参透Delphi》一书中说是指向:VMT。
在《Delphi对象模型》中说:
在Delphi中,类表现为内存中一张只读的表,表中存放着指向该类的虚方法的指针以及其他许多信息。
创建的对象的头4个字节存放的是一个类引用(Class reference)就是指向该表的一个指针,而该表的头4个字节又是一个指向VMT的指针。

我觉得应该是指向VMT的,做过测试也表明了:)

2004年11月2日 16:51
评论
  • # 回复: 对象实例在内存中头4个字节指向的值
    reallike
    2004-11-2 17:17
    《Delphi对象模型》说的是正确的。

    关键代码在这里:

    function TObject.ClassType: TClass;
    begin
    Pointer(Result) := PPointer(Self)^;
    end;

    TClass无疑是类引用。

    而用PPointer是类型的转换,指向指针的指针自然就是对象的头四个字节所作的工作。
  • # 回复: 对象实例在内存中头4个字节指向的值
    hottey
    2004-11-2 21:55
    RL:
    《Delphi对象模型》的说法对吗?以下是我的理解。
    {类中存在虚拟方法的情况:
    这里的Self可以理解为指向VMT的指针,实际上它的值就是VMT的基地址。
    而VMT的基地址,也就是存放(第一个虚拟方法地址)单元的地址。
    因此两种说法都没错,VMT的地址就是表的地址,它是以0开始的,因此
    参透Delphi中说的指向VMT表是对的,而Delphi对象模型中说是一个类引用
    创建TA的实例A后,Pointer(A)^就是VMT的基地址,也应该可以理解为TA的
    类引用。我错误的把VMT的首地址理解为相对基地址偏移-76处的地址了}
    Type
    { TA类 }
    TA = class(TObject)
    public
    Class function SelfPtr: Pointer;
    procedure V;virtual;
    end;

    TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    end;

    var
    Form1: TForm1;

    implementation
    {$R *.dfm}
    { TA类 }

    Class function TA.SelfPtr: Pointer;
    begin
    ShowMessage(inttohex(integer(Self),8));
    //Self的值实际为类的虚拟表的基地址, 此处值为 $00451F90
    //它和 ShowMessage(inttohex(integer(TA),8)); 的效果是一样的。
    Result := PPointer(Integer(Self) + vmtSelfPtr)^;
    //得到偏移-76处的指针,相对虚拟表的基地址
    end;

    procedure TA.V();
    begin
    //
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    var
    A: TA;
    P: Pointer;
    Func: procedure of object;
    begin
    P := TA.SelfPtr;
    //P为偏移-76处存放的指针变量
    ShowMessage(inttohex(integer(P),8));
    //此处P的值为 $00451F90
    //可以看出P指向的是VMT的基地址,也就是存放(第一个虚拟方法入口地址)单元的地址。
    //P^ 的值为 $0045218C 即是A.V 的地址
    A := TA.Create();
    Func := A.V;
    ShowMessage(inttohex(integer(@Func),8));
    //虚拟方法 A.V 的地址 值为: $0045218C
    ShowMessage(inttohex(integer(Pointer(A)^),8));
    //值为:$00451F90
    end;
  • # 回复: 对象实例在内存中头4个字节指向的值
    hottey
    2004-11-2 22:40
    类中有没有虚拟方法存在时:
    ShowMessage(inttohex(integer(Pointer(A)^),8));
    //它的值都为:$00451F90
    并不像我以前想像的那样是为nil的。

    如这个帖的内容:http://hottey.mblogger.cn/posts/10626.aspx
  • # 回复: 对象实例在内存中头4个字节指向的值
    李马
    2004-11-2 22:59
    和C++对象模型的vptr差不多
  • # 回复: 对象实例在内存中头4个字节指向的值
    reallike
    2004-11-3 8:40
    我不明白你这句话的意思。字体太小,我不打算回复了。

    Result := PPointer(Integer(Self) + vmtSelfPtr)^;

    你用了vmtSelfPtr这个虚函数表的偏移量,就等于开始使用虚函数表,你在证明什么?我不清楚。

    我只是说一句话,对象所指向的头四个字节是类引用。

    就是这个:

    function TObject.ClassType: TClass;
    begin
     Pointer(Result) := PPointer(Self)^;
    end;

    你要知道Self指针作了什么,你用了一个类方法取得Self指针的地址,如果你没有创建对象,Self指针是个类引用!

    也就是说,这个类方法误导了你:

    Class function TA.SelfPtr: Pointer;
    begin
     ShowMessage(inttohex(integer(Self),8));
    end;

    这时候,在你的对象建立之前,你Self指针取得的,是一个类引用的地址。所以你取得错误的答案。帮助如下:

    In the defining declaration of a class method, the identifier Self represents the class where the method is called (which could be a descendant of the class in which it is defined). If the method is called in the class C, then Self is of the type class of C. Thus you cannot use Self to access fields, properties, and normal (object) methods, but you can use it to call constructors and other class methods.
    A class method can be called through a class reference or an object reference. When it is called through an object reference, the class of the object becomes the value of Self.
  • # 回复: 对象实例在内存中头4个字节指向的值
    reallike
    2004-11-3 8:42
    看看最后一句,A class method can be called through a class reference or an object reference.

    你的Self指针到底是什么值。检测一下。

    不在多做答复,字体太小,我眼睛不舒服……
  • # 回复: 对象实例在内存中头4个字节指向的值
    hottey
    2004-11-3 10:35
    reallike:
    感谢你的回复,我会好好看的:)

    PS:我也不知道字体为什么会这么小,我打开你们的Blog时字体更小,晕。是不是我的设置有问题?
  • # 回复: 对象实例在内存中头4个字节指向的值
    reallike
    2004-11-3 11:23
    设置浏览器中的查看,字体大小。选择为中等。大家都这么做。
  • # re
    sonneries portables
    2005-2-5 0:46
    a very great and interesting blog
主题  
姓名  
主页
验证码  
内容   
 

请不要发表可能给我们带来伤害的政治言论,谢谢配合