C++: How to count all instantiated objects at runtime?
I have a large framework consisting of many C++ classes. Is there a way using any tools at runtime, to trace all the C++ objects that are being constructed and currently exist?
For example, at a certain time t1, perhaps the a开发者_如何学编程pplication has objects A1, A2 and B3, but at time t2, it has A1, A4, C2 and so on?
This is a cross platform framework but I'm familiar with working in Linux, Solaris and (possibly) Mac OS X.
You can inject code in the destructor and constructor of the objects that you want to count:
SomeObject::SomeObject() {
++globalSomeObjectCounter;
}
SomeObject::~SomeObject() {
--globalSomeObjectCounter;
}
Don't forget to increase the counter in all constructors (copy constructors, etc.)
EDIT: In this situation one can use the curiously recurring template pattern:
template <typename T>
struct Counter
{
Counter() {++counter;}
virtual ~Counter() {--counter;}
static int counter;
};
template <typename T> int Counter<T>::counter(0);
and then:
class SomeObject : public Counter<SomeObject> {
}
to automatically generate a counter for each class type.
I assume that you count only objects on the heap. If this is the case, you can log all calls to new and delete by replacing them with some custom macros.
We have developed such a custom logging facility. The primary purpose was to track memory leaks, but it can also be used to find out how many objects at any specific time. For example,
#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);
The MY_LOGGING adds timestamp automatically at the beginning of each line. The line has the class name, filename, line number, function name, and the size.
A utility parses the logging file and generates graphs showing the number of objects, total size utilized etc at any time.
Of course, you have to replace every new/delete calls with the macros. Which might be quite a bit work.
I have not used it myself by Massif might be the tool you are looking for. http://valgrind.org/info/tools.html
Make a special base class equivalent to Java's Object and make every class derive from that. Then in that class put the global counter operations Andreas Brinck suggests in the constructor/destructor respectively. In addition to making sure a derived object is only counted as one object, it means you only need to instrument 1 constructor and 1 destructor. Though of course the downside is you need to slightly change the definition of every class...
This is Solaris only, but if that's an option, you can use dtrace to track the number of constructor and destructor calls for each of your classes and print it out at an interval. This will require an amount of work to set up all the entry/return blocks, but I suspect the dtrace script could be auto-generated.
精彩评论