Memory tracer and placement new

Started by
3 comments, last by Hedanito 10 years, 6 months ago

So I have this memory tracer I wrote a while back which has worked perfectly since then.

It works by overwriting new, delete, malloc, etc and a static manager class will keep track of everything

Basically like this:


void* operator new (Core::uintp a_Size, const Core::char8* a_File, Core::uint32 a_Line);
void* operator new[] (Core::uintp a_Size, const Core::char8* a_File, Core::uint32 a_Line);
void operator delete (void *a_Memory, const Core::char8* a_File, Core::uint32 a_Line);
void operator delete[] (void *a_Memory, const Core::char8* a_File, Core::uint32 a_Line);
void operator delete (void *a_Memory);
void operator delete[] (void *a_Memory);

#define malloc(a_Size) MemoryTracer::Malloc(a_Size, __FILE__, __LINE__)
#define realloc(a_Memory, a_Size) MemoryTracer::Realloc(a_Memory, a_Size, __FILE__, __LINE__)
#define calloc(a_Count, a_Size) MemoryTracer::Calloc(a_Count, a_Size, __FILE__, __LINE__)
#define free(a_Memory) MemoryTracer::Free(a_Memory, __FILE__, __LINE__)

#define new new(__FILE__, __LINE__)
#define delete MemoryTracer::SetFreeInfo(__FILE__, __LINE__), delete

This worked fine for pretty much everything, until now.

I am currently writing a container class which has to use placement new.

The #define new new(__FILE__, __LINE__) messes up the placement new syntax.

Another problem is that placement new cannot be overwritten.

I am not sure what the best solution is for this problem, so I was hoping you guys could give me some suggestions.

Since the placement new doesn't allocate any memory, the solution does not have to involve the memory tracer.

I just want to keep the syntax as close to normal C++ as possible.

Advertisement

I also wrote such a thing for detecting leaks and this is how I made it work.

Dont include the header with the code you posted there in the .cpp file where you need the placement new.

Alternatively do the .cpp file like this:


#define NEW_WITH_FILE_LINE
#include "yourheader.h"

// the code where you need placement new

and change the header to surround the last 2 #define with an #ifdef NEW_WITH_FILE_LINE and #endif .

Also make sure your allocator overwrites the normal new in a way to make it compatible with the version that includes the __FILE__ and __LINE__ infos.

You can also use the information which version was called to choose only parts of your application for a deeper check or sorting the output of your memory checker.

What I've seen for most memory managers that #define new is a two header system: one that has all the #defines and one that #undefs all of the defines. Let's say you have enable.h and disable.h (though you probably should choose something more descriptive than this). You would #include "enable.h" in the files you want to use your tracking functions. However, when including a file that uses placement new you would do something like:

#include "disable.h"
#include <vector>
#include "enable.h"

The standard way around this is to not #define new. Instead you override global operator new (and all it's variants like the nothrow one) and in your global operator new implementation you walk the stack to find out where the allocation came from.

You'll probably also want to use some linker trickery to wrap functions like malloc() and do the same thing.

Fortunately you don't need to worry about implementing it yourself if you're using Visual Studio because VLD does exactly that and it's free.

Thanks guys, it seems that undefining new is the way to go.

I just have a define and undefine header now, and the define header is automatically included with the memory manager.

It is not the prettiest solution, but since placement new is so rare I can live with it.

This topic is closed to new replies.

Advertisement