2

What is the best way to monitor memory allocation/de_allocation in the source code. I have a C++ program which allocates large amount of memory dynamically and I want to keep track of that which object from which class is taking and freeing memory.

What I want in the output of my program is:

Creating Object from ClassA, Memory Usage ...
Creating Object from ClassB, Memory Usage ...
...
Freeing  Object from ClassA, Memory Freed ...

What I'm doing now is simply overloading global new operator, but I heard it is not very safe. Moreover, I need a way that dose't require to change all of my classes (i.e. using a base class and all classes have a string variable ClassName).

------------------------------------- Edit --------------------------------------

1- I don't want to use external tools and need to do it in the code.

2- If I overload global new operator, how I can access the Name of class or other members?

Roy
  • 65
  • 2
  • 15
  • 40
  • 2
    There is no problem with doing that. We even a SO C++ FAQ [How should i write iso c standard conformant custom new and delete operators](http://stackoverflow.com/questions/7194127/how-should-i-write-iso-c-standard-conformant-custom-new-and-delete-operators) – Martin York Aug 29 '12 at 16:32
  • @Loki: If I define new globally and want to put print command in it, how I can access my class name? – Roy Aug 29 '12 at 16:36
  • 2
    You can't get the class name. The global new operator only gets the size. You could write a new operator for each class but at that point it becomes easier to put a print statement in each constructor. – Martin York Aug 29 '12 at 16:39
  • 1
    @Hesam If you define new globally, and want to output in it, you'd best take some precautions about endless recursion. Output functions may call `new`. – James Kanze Aug 29 '12 at 16:42
  • 1
    @Hesam: Also, you can call `new` as `::new`; several Boost libraries like doing this. That will pretty much hose your attempt to redefine `new`. – Nicol Bolas Aug 29 '12 at 16:44
  • Can I define a global static variable called class name and in the ctor of any class rewrite it and in the global new use that to print? Is new called after ctor or before it? – Roy Aug 29 '12 at 16:47

4 Answers4

2

Take a look at MS tool called application verifier also take a look VS2010 profiler.

Mahmoud Fayez
  • 3,398
  • 2
  • 19
  • 36
  • I don't want to use external tools and need to do it in the code. – Roy Aug 29 '12 at 16:37
  • 1
    Then override the new/delete operator and make use of these macros in the following url: http://msdn.microsoft.com/en-us/library/b0084kay(v=vs.80).aspx – Mahmoud Fayez Aug 29 '12 at 20:41
  • 1
    Also use this tool if you are happy with that: http://www.codeproject.com/Articles/19388/Memory-leak-detection-in-C it may give you inspiration of how to make your own code. – Mahmoud Fayez Aug 29 '12 at 20:43
1

I hate this tool for tracking down memory leaks, but for monitoring allocs/dellocs it should do what you want: UMDH.

oz10
  • 153,307
  • 27
  • 93
  • 128
1

In highly depends on whether you want to do it in development only or in production as well and what your performance requirements are. For development on Linux you would normally start from Valgrind's Massif, if you are looking at a more custom solution and/or production mode you may look at combining malloc/calloc/realloc overriding code (my example here) with libunwind.

bobah
  • 18,364
  • 2
  • 37
  • 70
  • 1
    Technically there is no language way of overriding malloc/calloc/delete (you have to use platform specific tricks like pre-loading). But C++ provides a mechanism for overiding new/delete at the language level (so this is the preferred technique for C++ applications). Also worth noting there is no requirement for new/delete to actually use malloc/delete the standard actually states that new/delete get memory from the "Free Store" while malloc/delete get memory from the "Heap" weather these areas overlap is implementation defined. – Martin York Aug 29 '12 at 16:44
  • @LokiAstari - it's true and that's why I started my answer with "it highly depends", but as a matter of fact, 99.9% of software on Linux is built with glibc and have new/delete implemented via malloc/calloc/free. Malloc override can be plugged into an existing software without rebuild via LD_PRELOAD, which may be a preferable way for many (including myself), as opposed to full software rebuild with new/delete override. – bobah Aug 30 '12 at 08:09
1

2- If I overload global new operator, how I can access the Name of class or other members?

You can't. You have to understand that the new and delete operators are not straight function calls. In effect, a syntax like MyClass* p = new MyClass(); is equivalent to:

MyClass* p = (MyClass*) malloc(sizeof(MyClass)); // A) allocate the memory.
new(p) MyClass(); // B) call constructor (via placement-new syntax (to illustrate)).

While a delete p; is equivalent to:

p->~MyClass();  // C) call destructor.
free(p);        // D) free the memory.

When you overload the new-delete operators, all that the compiler actually permits you to overload are the steps A) and D), respectively. In other words, when you reach the body of the custom new operator, the object is not yet created, and thus, you can't access or print any information about it (class, name, etc.), except its address in memory, which you could print in your overloaded new. Similarly, by the time you reach your custom delete operator, the object has been destroyed and any attempts to use any information that might still be dangling in that memory is undefined behavior, especially if you want to use a virtual function or a string value.

Really, the best you can do with this approach is to print the pointers created in the new operator and print the pointers deleted by the delete operator.

And, as others have mentioned, you must be wary of infinite recursions when doing operations within the new-delete operators. For example, a simple line like:

std::cout << "Created pointer: " << reinterpret_cast<std::size_t>(p) << std::endl;

will almost certainly cause many calls to new and delete (creating temporary strings, extending buffers, etc.).

So, you'd probably have to either come up with a clever way to output the log messages you want to output without causing any new-delete to happen, or you will have to restrict your new-delete operator overloads to only the classes of your framework. For the latter, the simplest thing is to put it in a base class. The other option is to use a bit of MACRO magic, but this will still be intrusive and cumbersome.

And, at this point, if you have to create a base-class (for all your library's classes) which handles this logging of creation-deletion (or create a set of MACROs to be put in each class you create), you might as well use the constructor / destructor instead as the place for printing those log messages, and leave the new-delete operators intact.

1- I don't want to use external tools and need to do it in the code.

Why not? It is very likely that an external tool (a VM like Valgrind, or a general profiler / memory tracer) will do a far better and less intrusive job than you will.

Mikael Persson
  • 18,174
  • 6
  • 36
  • 52
  • Thanks, I suppose that your description about not having access to class members also apply if I want to overload operator new in the base class (instead of global new). Is this a good idea: I Just print amount of memory in the new operator and in the constructor of base class I print the name. So name of class comes after amount of memory. – Roy Aug 29 '12 at 18:32
  • 1
    @Hesam: Yes my description applies identically for a new operator in the base class. If you make a base-class, then I guess it is fine to use the new-op to print the size and the constructor to print the name, but you won't be able to print the size in the delete-op though. So, I don't know how meaningful it would be to print only the size allocated, and not the size deallocated. – Mikael Persson Aug 29 '12 at 19:28