Poor Man's C++ Memory Profiler

Here is a quick and easy way to profile memory of C++ programs by simply overriding the default new/delete operators. Just add this to your program source (you don't even have to call it):

/* Who called me?  */
void* caller()
{
    // The target is the caller's caller, so three functions back
    const int target = 3;
    void* returnaddresses[target];
    if (backtrace(returnaddresses, target) < target) {
        return NULL;
    }
    return returnaddresses[target-1];
}


void* operator new(size_t size) throw(std::bad_alloc) {
    void* ret = malloc(size);
    if (!ret) throw std::bad_alloc();
    fprintf(stderr, "allocate: %p %d bytes from %p\n", ret, size, caller());
    return ret;
}

void* operator new[] (size_t size) throw(std::bad_alloc) {
    void* ret = malloc(size);
    if (!ret) throw std::bad_alloc();
    fprintf(stderr, "allocate: %p %d bytes from %p\n", ret, size, caller());
    return ret;
}

void operator delete (void* data)
{
    free(data);
    fprintf(stderr, "free: %p\n", data);
}

void operator delete [] (void* data)
{
    free(data);
    fprintf(stderr, "free: %p\n", data);
}

Your program will spew output about all the new/delete allocations it performs. Run that through this awk snippet to get a useful report:

awk '/^free: /       { fun[owner[$2]] -= size[$2]; delete size[$2]; delete owner[$2]; }
     /^reallocate: / { fun[owner[$2]] -= size[$2]; delete size[$2]; delete owner[$2];
                       size[$4] = $6; owner[$4] = $9; fun[$9] += $6; }
     /^allocate: /   { size[$2] = $3; owner[$2] = $6; fun[$6] += $3; }
     END { for(i in fun) { print i " has " fun[i] " bytes"; }}' |
sort -k3n

Alternatively, you can omit the print statements here but keep the new/delete → malloc/free connection and use the malloc/free profiler. This is handy for misbehaved programs that free new-ed things or delete malloc'd things.