12

System.pas 文件包含大量有关硬编码 VMT 偏移的信息,但它似乎并没有真正说明 VMT 本身的结构。我真正想知道的是,有没有办法在运行时找出 VMT 的大小,或者换句话说,给定类存在多少虚拟方法?

4

5 回答 5

14

你想知道 VMT 结构怎么样?您也知道这是一个内部实现细节,可能会发生变化(并且随着时间的推移而变化)。

要回答您的具体问题,这里有一个简单的方法来查找给定类的虚拟方法的数量:

function GetVirtualMethodCount(AClass: TClass): Integer;
begin
  Result := (PInteger(Integer(AClass) + vmtClassName)^ - 
    (Integer(AClass) + vmtParent) - SizeOf(Pointer)) div SizeOf(Pointer);
end;

这是有效的,因为我碰巧知道代表类名的字符串紧跟在 VMT 中的所有虚拟方法向量之后。

我还知道所有与 VMT 指针本身负偏移的 TObject 上有 11 个虚拟方法(对于 D2009,对于 D2007 和之前的版本有 9 个)。

这就是 vmtParent 引用的原因。

最后,通过使用 TClass 类引用,您可以将任何 TObject 派生类传递给此函数并获取虚拟方法的数量。

于 2009-04-17T16:19:58.000 回答
10

我很确定 Hallvard 在 VMT 上有一些东西。果然,他有Hack #8: Explicit VMT calls,它引用了 Ray Lischner Secrets of Delphi 2Delphi in a Nutshell

这是他破解的 VMT 版本

type
  PClass = ^TClass;
  PSafeCallException = function  (Self: TObject; ExceptObject:
    TObject; ExceptAddr: Pointer): HResult;
  PAfterConstruction = procedure (Self: TObject);
  PBeforeDestruction = procedure (Self: TObject);
  PDispatch          = procedure (Self: TObject; var Message);
  PDefaultHandler    = procedure (Self: TObject; var Message);
  PNewInstance       = function  (Self: TClass) : TObject;
  PFreeInstance      = procedure (Self: TObject);
  PDestroy           = procedure (Self: TObject; OuterMost: ShortInt);
  PVmt = ^TVmt;
  TVmt = packed record
    SelfPtr           : TClass;
    IntfTable         : Pointer;
    AutoTable         : Pointer;
    InitTable         : Pointer;
    TypeInfo          : Pointer;
    FieldTable        : Pointer;
    MethodTable       : Pointer;
    DynamicTable      : Pointer;
    ClassName         : PShortString;
    InstanceSize      : PLongint;
    Parent            : PClass;
    SafeCallException : PSafeCallException;
    AfterConstruction : PAfterConstruction;
    BeforeDestruction : PBeforeDestruction;
    Dispatch          : PDispatch;
    DefaultHandler    : PDefaultHandler;
    NewInstance       : PNewInstance;
    FreeInstance      : PFreeInstance;
    Destroy           : PDestroy;
   {UserDefinedVirtuals: array[0..999] of procedure;}
  end;

不过,您需要阅读他的文章以了解有关该 hack 的更多信息。

于 2009-04-17T16:30:36.647 回答
3

我将为此插入我自己的网站:

什么是虚方法表?

我认为它在 Delphi 2005 中是准确的。

VMT 没有给出它持有的虚拟方法指针数量的任何值。只有编译器需要知道这些信息,所以没有理由记录它以供在运行时使用。

于 2009-04-17T16:20:23.693 回答
2

谷歌搜索 :-P 为“delphi vmt”会产生这个。也许这会给你一个开始。

于 2009-04-17T14:27:30.967 回答
0

我记得在“delphi in a nutshell”一书中有一些关于 delphi vmt 的信息。简而言之,你可以从delphi 第 2 章这个开始

于 2009-04-17T14:57:12.193 回答