2012-05-10 36 views
1

如何在Delphi 7中追蹤內存中某個類的計數,而無需在類中添加靜態計數成員。 用於跟蹤程序性能。 先進的謝謝。如何跟蹤delphi中某個類的實例數?

+0

如果這個類有它自己的(虛擬的或不是)的構造函數和析構函數,並且它足夠長,你可以查看鉤住這些的代碼,以便你可以在其他地方進行計數。 madCodeHook(http://madshi.net)是一個衆所周知的庫。 –

+0

@WarrenP:可能是因爲他沒有源代碼,或者它是您不想更改源代碼的組件,即使您擁有它。 –

+2

是的。我只是想到了。如果這只是表現,那麼只有一個答案是理智的;購買AQTIME。殘酷的昂貴,是的。討厭的一點HASP許可廢話附加到它。是。但是,真棒工具。 –

回答

4

你可以連接在類VMT的NewInstance方法和FreeInstance方法:

unit ClassHook; 

{no$DEFINE SINGLE_THREAD} 

interface 

var 
    BitBtnInstanceCounter: integer; 

implementation 

uses Windows, Buttons; 

function GetVirtualMethod(AClass: TClass; const VmtOffset: Integer): Pointer; 
begin 
    Result := PPointer(Integer(AClass) + VmtOffset)^; 
end; 

procedure SetVirtualMethod(AClass: TClass; const VmtOffset: Integer; const Method: Pointer); 
var 
    WrittenBytes: {$IF CompilerVersion>=23}SIZE_T{$ELSE}DWORD{$IFEND}; 
    PatchAddress: PPointer; 
begin 
    PatchAddress := Pointer(Integer(AClass) + VmtOffset); 
    WriteProcessMemory(GetCurrentProcess, PatchAddress, @Method, SizeOf(Method), WrittenBytes); 
end; 

{$IFOPT W+}{$DEFINE WARN}{$ENDIF}{$WARNINGS OFF} // avoid compiler "Symbol 'xxx' is deprecated" warning 
const 
    vmtNewInstance = System.vmtNewInstance; 
    vmtFreeInstance = System.vmtFreeInstance; 
{$IFDEF WARN}{$WARNINGS ON}{$ENDIF} 

type 
    TNewInstanceFn = function(Self: TClass): TObject; 
    TFreeInstanceProc = procedure(Self: TObject); 

var 
    OrgTBitBtn_NewInstance: TNewInstanceFn; 
    OrgTBitBtn_FreeInstance: TFreeInstanceProc; 

function TBitBtn_NewInstance(Self: TClass): TObject; 
begin 
    Result := OrgTBitBtn_NewInstance(Self); 
    {$IFDEF SINGLE_THREAD} 
    Inc(BitBtnInstanceCounter); 
    {$ELSE} 
    InterlockedIncrement(BitBtnInstanceCounter); 
    {$ENDIF} 
end; 

procedure TBitBtn_FreeInstance(Self: TObject); 
begin 
    {$IFDEF SINGLE_THREAD} 
    Dec(BitBtnInstanceCounter); 
    {$ELSE} 
    InterlockedDecrement(BitBtnInstanceCounter); 
    {$ENDIF} 
    OrgTBitBtn_FreeInstance(Self); 
end; 

procedure InstallHooks; 
begin 
    OrgTBitBtn_NewInstance := GetVirtualMethod(TBitBtn, vmtNewInstance); 
    OrgTBitBtn_FreeInstance := GetVirtualMethod(TBitBtn, vmtFreeInstance); 
    SetVirtualMethod(Buttons.TBitBtn, vmtNewInstance, @TBitBtn_NewInstance); 
    SetVirtualMethod(Buttons.TBitBtn, vmtFreeInstance, @TBitBtn_FreeInstance); 
end; 

procedure RemoveHooks; 
begin 
    SetVirtualMethod(Buttons.TBitBtn, vmtNewInstance, @OrgTBitBtn_NewInstance); 
    SetVirtualMethod(Buttons.TBitBtn, vmtFreeInstance, @OrgTBitBtn_FreeInstance); 
end; 

initialization 
    InstallHooks; 

finalization 
    RemoveHooks; 

end. 

在程序中包含的任何uses條款本機現在BitBtnInstanceCounter將跟蹤TBitBtn實例數。

編輯:如果有可能多個線程同時創建跟蹤類的對象,則需要使用互鎖訪問來修改計數器變量。請注意,第三方組件可以靜靜地使用線程,因此不定義SINGLE_THREAD符號更安全。

3

有沒有內置的方式來做到這一點。某些分析器(AQTime?)通過安裝自定義堆管理器鉤子,然後查看位於任何對象開始處的類型指針,爲您生成此類度量標準。你可以自己做,但如果這是在開發過程中進行分析,那麼只要使用已經由其他人開發和測試的內容就容易多了。

相關問題