[英]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.