Replacing new

Started by
5 comments, last by Doggan 18 years, 3 months ago
I want to replace new with a version which (in debug mode) tracks allocations, can tell me the memory usage, the number of allocations, report memory leaks etc. My initial thoughts was doing something like Fluid Studio’s MMGR and define a macro called new which pointed to my custom version of new. Like this:

inline void* new(size_t size,unsigned int line,const std::string& file)
{
    //…
}
#define new new(__LINE__,__FILE__)

There is one very big problem with this though, imagine this class:

class a
{
public:
    static void* operator new(size_t size)
    {
        return ::operator new(size); 
    }
};

The problem is the preprocessor will replace new with something like new(5,”a.hpp”). So the code the compiler would get would look like this:

class a
{
public:
    static void* operator new(4,"a.hpp") (size_t size)
    {
        return ::operator new(6,"a.hpp")(size); 
    }
};

And this will give me a syntax error, so is there any work around for this? The only solution I can see is defining a macro custom_new to new(__LINE__,__FILE__) instead of new to new(__LINE__,__FILE__).
Advertisement
There are two possibilities:

1). Just use the Fluid Studio! Why do you want to write your own memory tracking code when Fluid Studio's version has been around a while, and has been tested very well? In case you only saw the old FlipCode article.... the complete source code to the mem manager is found here: http://www.fluidstudios.com/pub/FluidStudios/MemoryManagers/Fluid_Studios_Memory_Manager.zip. I have used this is many projects. Include the header into all your source files, and it will print you out nice .txt reports of all the memory leaks in your application.

2). Declaring a global new macro is one of the biggest headaches I've run into. In addition to the problem you just pointed out, you will also come across problems when including other standard header files, and the 'new's clashing. Instead of taking this approach, go with a base Object class. All your classes can be derived from a base object class. This can be used to assign unique ids to all objects in your app, as well as handle memory management in a central location (it can declare it's own "new" declaration that is inherited by all subclasses).
Thanks for the reply

Quote:
1). Just use the Fluid Studio! Why do you want to write your own memory tracking code when Fluid Studio's version has been around a while, and has been tested very well? In case you only saw the old FlipCode article.... the complete source code to the mem manager is found here: http://www.fluidstudios.com/pub/FluidStudios/MemoryManagers/Fluid_Studios_Memory_Manager.zip. I have used this is many projects. Include the header into all your source files, and it will print you out nice .txt reports of all the memory leaks in your application.

I want more functionality than the Fluid Studio's memory manager, additional to finding memory leaks I want to give statistics of memory (global peak usage, peak usage in specific modules, number of allocations, the size most frequently allocated with new, real-time graphical monitoring etc.) also I need to send all the data to another application of mine instead of writing to a txt file.

Quote:
Instead of taking this approach, go with a base Object class. All your classes can be derived from a base object class. This can be used to assign unique ids to all objects in your app, as well as handle memory management in a central location (it can declare it's own "new" declaration that is inherited by all subclasses).

I didn't know that was possible, it would definatly solve all of my problems. Do you have a link to an article or something which shows how this is accomplished?
I have searched for hours now and can't find anything like the operator new you are talking about, the only kind of overloads I could find was the ones I already knew, global and a class' own new operator (where that new is called when the class is constructed with new, not when the class constructs objects with new).

Can anyone please confirm that it is possible to create a "local new".
struct BaseObject{    BaseObject() {};    virtual ~BaseObject() {};    static void *operator new (size_t size)    {        int i = 0;        void *p = malloc( size );        return p;    }    static void operator delete (void *p) {}};class AnotherChildObject : public BaseObject{public:    AnotherChildObject() {};    virtual ~AnotherChildObject() {};};class ChildObject : public BaseObject{public:    ChildObject() {        AnotherChildObject *aco = new AnotherChildObject();    }    virtual ~ChildObject() {};};int main(int argc, _TCHAR* argv[]){    ChildObject *co = new ChildObject();	return 0;}


...is what I meant. All the 'news' here reference the same function. If all the objects you create with new are derived from this BaseObject, you have a centralized location to track all your memory allocations from.
Quote:Original post by Doggan
*** Source Snippet Removed ***

...is what I meant. All the 'news' here reference the same function. If all the objects you create with new are derived from this BaseObject, you have a centralized location to track all your memory allocations from.


Thanks, unfortunately I thought what you meant was that all memory allocations inside BaseObject, ChildObject and AnotherChildObject would use the custom new operator (including stuff like ints and third-party objects).

Well the solution I will use then is to make a macro like this:
// mm short for memory managed#define mm set_file(__FILE__);set_line(__LINE__);memory_managed = true;


And then I will overload the standard new operator (only taking one parameter) and call new like this:
mm int a = new int;

memory_managed will then be set to false inside new, so if I don't use mm on the next new statement it wont be memory managed.
I found some code I used long ago. The majority was from some article I read... I changed a few things, though. If you're going this route, hopefully this code can help.

#ifndef _MEMORYMANAGEMENT_H_#define _MEMORYMANAGEMENT_H_#	ifdef _DEBUG// MSVC specific memory leak detection.#define CRTDBG_MAP_ALLOC#include <stdlib.h>#include <crtdbg.h>#define dbgMalloc(s)       _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)#define dbgCalloc(c, s)    _calloc_dbg(c, s, _NORMAL_BLOCK, __FILE__, __LINE__)#define dbgRealloc(p, s)   _realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__)#define dbgExpand(p, s)    _expand_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__)#define dbgFree(p)         _free_dbg(p, _NORMAL_BLOCK)#define dbgMemSize(p)      _msize_dbg(p, _NORMAL_BLOCK)#define dbgNew new(_NORMAL_BLOCK, __FILE__, __LINE__)#define dbgDelete delete// Set to dump leaks at the program exit. Should be called at program initialization.#define dbgInitMemoryCheck() 	_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF)#	else	// Release build.#define dbgMalloc malloc#define dbgCalloc calloc#define dbgRealloc realloc#define dbgExpand _expand#define dbgFree free#define dbgMemSize _msize#define dbgNew new#define dbgDelete delete#define dbgInitMemoryCheck()#	endif#endif // _MEMORYMANAGEMENT_H_

This topic is closed to new replies.

Advertisement