C++:如何在运行时统计所有实例化的对象数量?

8

我有一个由许多C++类组成的大型框架。在运行时,有没有一种方法可以使用任何工具来跟踪正在创建和存在的所有C++对象?

例如,在某个时间t1,可能应用程序具有对象A1、A2和B3,但在时间t2,它具有A1、A4、C2等。

这是一个跨平台的框架,但我熟悉在Linux、Solaris和(可能)Mac OS X上的工作。

5个回答

10
你可以在你想要计数的对象的析构函数和构造函数中注入代码:
SomeObject::SomeObject() {
   ++globalSomeObjectCounter;
}

SomeObject::~SomeObject() {
   --globalSomeObjectCounter;
}

不要忘记在所有构造函数(拷贝构造函数等)中增加计数器。

编辑:在这种情况下,可以使用奇异递归模板模式:

template <typename T>
struct Counter
{
    Counter() {++counter;}
    virtual ~Counter() {--counter;}
    static int counter;
};
template <typename T> int Counter<T>::counter(0);

接着执行:

class SomeObject : public Counter<SomeObject> {
}

自动生成每个类类型的计数器。


但是如果您直接构造一个父类呢?没有任何保证它是抽象的。 - frankc
@user275455 您感兴趣的每个类都应该有自己的计数器。如果您构造一个 SomeObject,则 globalSomeObjectCounterglobalSomeObjectParentCounter 都会增加一个,这正是应该的。 - Andreas Brinck
析构函数也应该是虚拟的吧?据我所知,否则它将无法执行。 - Mike Bailey
我明白了,不知怎么的我以为你有一个全局计数器,而不是每个类一个计数器。这意味着你需要在其他地方知道所有计数器的名称才能得到所有对象的总和。 - frankc
好的,如果您需要在某个时间点获取所有对象的计数器,您只需访问每种类型的 Counter<Object_Type>::counter。 - Mike Bailey
显示剩余3条评论

1

我假设您只计算堆上的对象。如果是这种情况,您可以通过将它们替换为一些自定义宏来记录所有对new和delete的调用。

我们已经开发了这样一个自定义日志记录工具。主要目的是跟踪内存泄漏,但也可以用于查找任何特定时间点的对象数量。例如,

#define MY_NEW_OBJECT(a, T) \
    a = new T;              \
    MY_LOGGING((LM_DEBUG, "[NEW OBJ ] 0x%08X(%s), %4d bytes. %-20s - %-40s - %4d\n", a, #T,  \
    sizeof(T), __FILE__, __func__, __LINE__));

MyClass* myObj;
MY_NEW_OBJECT(myObj, MyClass);

MY_LOGGING会在每行开头自动添加时间戳。该行包括类名、文件名、行号、函数名和大小。

一个实用程序解析日志文件并生成图表,显示任何时间的对象数量、总大小等。

当然,您必须使用宏替换每个new/delete调用。这可能需要相当多的工作。


这仅计算动态分配的对象。那么局部变量、成员变量等呢? - Björn Pollex

0

根据那里的简短描述,Massif仅对堆进行配置文件。对象也可以在堆栈上实例化。 - Björn Pollex

0
创建一个特殊的基类,相当于Java的Object,并使每个类都从该基类派生。然后在该类中,在构造函数/析构函数中放置Andreas Brinck建议的全局计数器操作。除了确保派生对象仅被计算为一个对象之外,这意味着您只需要检测1个构造函数和1个析构函数。当然,缺点是您需要稍微更改每个类的定义...

通过这种方式,无法知道每个类别已经构造了多少个对象,请参考我的编辑过的答案。 - Andreas Brinck
这是真的,但我并没有认为那是一个要求。我的理解,正确或错误,是所有对象的计数为1。 - frankc

0

这只适用于 Solaris,但如果您可以使用 dtrace 选项,可以跟踪每个类的构造函数和析构函数调用次数,并在一定间隔内打印出来。这将需要设置所有进入/返回块的一定量工作,但我怀疑 dtrace 脚本可以自动生成。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接