Associating C++ new with constructor

Ross Boylan
2007-02-15T07:35:24Z

This is NOT about the problems setting a breakpoint on a C++
constructor!

I've been looking for a way to count creations and destructions of C++
objects, with the counts kept on a per class basis. I've looked at
various tools to track memory use, but none of them appear to provide
this directly (even when attention is limited to the free store).
Some capture the call stack when the call to new is made, but this
doesn't definitively identify the class in question. (It can provide
the line of the call, but that's an imperfect indicator. If there are
multiple calls on one line, or the call is split over several lines,
things are ugly. And if we have
template<typename T> class Foo {
.....
T* p = new T(); // maybe needs to be new typename T()?
.....
};
the source is insufficient to identify the type.)

The problem is that the call to new precedes the call to the
constructor; new doesn't know the type, and the type is not on the
call stack.

Might it be possible, programmatically, to trace the stack up, locate
the call that will be made next, and get the constructor that way?

Here's a toy example on linux-i386:
Source line is
A *pA = new A();
disassembly
0x08048c9c <main+86>: movl $0x2c,0xc(%esp)
0x08048ca4 <main+94>: movl $0x804910d,0x8(%esp)
0x08048cac <main+102>: movl $0x8049166,0x4(%esp)
0x08048cb4 <main+110>: movl $0x4,(%esp)
0x08048cbb <main+117>: call 0x8048eac <_ZnwjPKcS0_m>
0x08048cc0 <main+122>: mov %eax,%ebx
0x08048cc2 <main+124>: mov %ebx,(%esp)
0x08048cc5 <main+127>: call 0x8048e9e
0x08048cca <main+132>: mov %ebx,0xfffffff4(%ebp)

The call stack has main+122 on it. Adding 5 gets me to the next call,
and
(gdb) info symbol 0x8048e9e
A::A() in section .text
(which I suppose is what the annotation in the disassembly was
about).

So my recipe is
a) get the address of the caller
b) add 5
c) extract the location being called there
d) get the symbol being called, and use it to identify the class
(this last step involves several substeps, including notably doing the
disassemly, getting the symbol, unmangling the symbol, and extracting
the class name).

Does that have any chance of working with any generality?

I'm not necessarily looking to do the instrumentation from within gdb,
though I'd certainly like to avoid having to redo the logic of getting
debug info, etc..

The most obvious concern is that calls to the c'tor might get
optimized away (for example, class A above is empty, but I compiled
with g++ -O0).

It would also be nice to get the address of new automatically. Can
anyone explain why this symbolic lookup failed? (the program wasn't
running)
(gdb) info symb 0x8048eac # works
operator new(unsigned int, char const*, char const*, unsigned long) in section .text
(gdb) info add 'operator new(unsigned int, char const*, char const*,
unsigned long)' # fails
No symbol "'operator new(unsigned int, char const*, char const*, unsigned long)'" in current context.
I tried several variants of the name for new; none worked.

Incidentally, it would be nice to be able to get all c'tor calls, not
just those associated with the heap, but that obviously does run into
the problems putting breakpoints on them. It would also require
identifying all the c'tors.

Thanks.
Ross Boylan