tags:

views:

232

answers:

2

I'm trying to write a memory profiler and so far have been able to get my custom functions to work for malloc, free, new and delete. I tried using __FILE__ and __LINE__ to log the originator inside the overloaded new method, but (as expected) it just gives the details of where the overloaded function is. Is there a way to get the details about the originator to the overloaded functions without doing any changes to existing code of the component being tested (like #define for malloc)?

The function I'm using is:

void* operator new (size_t size)
{
    if(b_MemProfStarted)
    {
     b_MemProfStarted = false;
     o_MemLogFile << "NEW: " << "| Caller: "<< __FILE__ << ":"
       << __LINE__ << endl;
     b_MemProfStarted = true;
    }

    void *p=malloc(size);
    if (p==0) // did malloc succeed?
    throw std::bad_alloc(); // ANSI/ISO compliant behavior

    return p;
}

The bool b_MemProfStarted is used to avoid recursive calls on ofstream and map.insert.

+1  A: 

You can write

new(foo, bar) MyClass;

In this case the following function is called

void*operator new(std::size_t, Foo, Bar){
    ...
}

You can now call

new(__LINE__, __FILE__) MyClass;

and use the data with

void*operator new(std::size_t, unsigned line, const char*file){
    ...
}

Adding a macro

#define new new(__LINE__, __FILE__)

to the code being monitored will catch most invocations without needing source code changes.

It's not perfect as you could call the operator new directly for example. In that case the preprocessor will turn your code into garbage. I know of no better way though.

Ben Strasser
As `new` is a keyword, attempting to re-define it with a macro is undefined behaviour (compiler specific extensions excepted). I prefer to conditional define a DEBUG_NEW_PLACEMENT macro for 'normal' `new`s and leave explicit `operator new` and special placement `new`s alone. It's still not a pretty solution, though.
Charles Bailey
void*operator new(std::size_t, unsigned line, const char*file) would fail because "new" just takes the size_t.Can't use "#define new new(__LINE__, __FILE__)" and operator override together since it would try to replace the "new" in the override function definition. void*operator new(std::size_t) -> void*operator new(__LINE__, __FILE__)/*recursive?*/(std::size_t)
Gayan
@Charles Bailey - Could you elaborate? I'm not familiar with DEBUG_NEW_PLACEMENTI tried "#define new(size) My_New(size, __FILE__, __LINE__)" but this doesn't seem to get called when doing a "new"
Gayan
@Gayan You can define operator new with additional parameters. You can even overload using them. The additional parameters have to be passed when invoking new as shown above. You will of course have to make sure, that you do not have the macro defined when writing the actual overload.
Ben Strasser
When using your over-ridden new function instead of regular new, you don't include the size_t parameter. The defines will do all the work to add the extra parameters.
Alan
A: 

No you can't do

#define new new(__FILE__, __LINE__)

but you can do:

#define DEBUG_NEW new(__FILE__, __LINE__)
#define new DEBUG_NEW

look at: http://sourceforge.net/projects/nvwa/

teZeriusz