简体   繁体   English

如何跟踪delphi中某个类的实例数量?

[英]How can I keep track of the number of instances there are of a certain class in delphi?

How can I track the count of a certain class in memory in Delphi 7, without adding a static counting member in the class. 如何在Delphi 7中跟踪内存中某个类的计数,而无需在该类中添加静态计数成员。 For the purpose of tracking the program performance. 为了跟踪程序性能。 Thank you in advanced. 在此先感谢您。

You can hook the NewInstance and FreeInstance methods in the class VMT: 您可以在类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.

Include this unit in any uses clause of your program and now the BitBtnInstanceCounter will track the count of TBitBtn instances. 包括在任何本机uses程序的条款,现在BitBtnInstanceCounter将跟踪的计数TBitBtn实例。

Edit: if it is possible that several threads simultaneously create objects of the tracked class, it is necessary to use interlocked access to modify the counter variable. 编辑:如果可能多个线程同时创建被跟踪类的对象,则必须使用互锁访问来修改计数器变量。 Beware that third-party components could silently use threads, so it's safer to not define the SINGLE_THREAD symbol. 请注意,第三方组件可以静默使用线程,因此不定义SINGLE_THREAD符号会更安全。

There's no built-in way to do that. 没有内置的方法可以做到这一点。 Some profilers (AQTime?) generate such metrics for you by installing a custom heap manager hook and then by looking at the type pointer that sits at the beginning of any object. 一些探查器(AQTime?)通过安装自定义堆管理器挂钩,然后查看位于任何对象开头的类型指针,为您生成此类指标。 You can do this yourself but if this is for profiling during development it's a lot easier to just use what's already been developed and tested by others. 您可以自己执行此操作,但是如果这是为了在开发过程中进行概要分析,则仅使用他人已经开发和测试的内容要容易得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM