2009-04-17 16 views
12

Il file System.pas contiene una discreta quantità di informazioni sugli offset VMT codificati, ma in realtà non sembra dire molto sulla struttura del VMT stesso. Quello che mi piacerebbe davvero sapere è, c'è un modo per scoprire le dimensioni di un VMT in fase di esecuzione, o in altre parole, quanti metodi virtuali esistono per una data classe?Dove posso trovare informazioni sulla struttura di Delphi VMT?

risposta

13

Cosa ne pensi della struttura del VMT? Sapete anche che si tratta di un dettaglio di implementazione interno che è soggetto a modifiche (e che è cambiato nel tempo).

Per rispondere alla tua domanda specifica, ecco un modo semplice per trovare il numero di metodi virtuali per una determinata classe:

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

Questo funziona perché mi capita di sapere che la stringa che rappresenta il nome della classe è posto seguendo immediatamente tutti i vettori del metodo virtuale nel VMT.

So anche che ci sono 11 metodi virtuali (per D2009, 9 per D2007 e precedenti) su tutti i TObject che sono sfalsati rispetto al puntatore VMT stesso.

Questo è il motivo per il riferimento vmtParent.

Infine, utilizzando un riferimento di classe TClass, è possibile passare qualsiasi classe derivata TObject in questa funzione e ottenere il numero di metodi virtuali.

+0

VmtEquals? Non ne ho mai sentito parlare prima. Equals è uno dei due nuovi metodi virtuali in TObject per Delphi 2009? –

+0

Sì. È necessario che alcune cose relative a Generics funzionino, credo. –

+0

Allen: È molto bello! Proprio quello che stavo cercando. Tu dici che la struttura può e cambia.Quindi quale versione (s) di Delphi fa questo trucco per? –

2

Googling :-P per "delphi vmt" produce this. Forse questo ti dà un inizio.

+2

* grin * Adoro Hallvard! È bravo a trucchi come questo. Sfortunatamente, definisce i virtual definiti dall'utente come un "array [0..999]", o in altre parole "più grande di quanto avrebbe mai dovuto essere." Sto cercando un modo per trovare la dimensione reale. –

1

mi collego il mio sito per questo uno:

What is the virtual-method table?

E 'preciso come di Delphi 2005, credo.

Il VMT non ha alcun valore che fornisce il numero di puntatori del metodo virtuale che detiene. Nient'altro che il compilatore deve sapere che informazioni, quindi non c'è motivo di registrarlo per l'uso in fase di esecuzione.

9

Ero abbastanza sicuro che Hallvard avesse qualcosa sul VMT. Abbastanza sicuro, ha Hack #8: Explicit VMT calls che fa riferimento a Ray Lischner Secrets of Delphi 2 e Delphi in a Nut.

Ecco la sua versione modificata up del 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; 

Avrete bisogno di leggere il suo articolo per ulteriori informazioni su l'hack però.

Problemi correlati