While trying out some memory tracking and preparation for my own memory manager, I tried to override the new operator. The article on flipcode was my main guideline in this process ( http://www.flipcode.com/archives/How_To_Find_Memory_Leaks.shtml ).
After implementing the techniques described in that article, I am left with the problem that somewhere in the STL the "crtdbg.h" is being included either directly or indirectly through some of the header-files that are being included (Using Visual Studio 2010).
This results in an error:
[...]10.0\vc\include\crtdbg.h(1078): error C2365: 'operator new' : redefinition; previous definition was 'function'
[...]10.0\vc\include\crtdbg.h(1078): error C2078: too many initializers
[...]
Doing a quick-check by placing the '_CrtDumpMemoryLeaks()' without including the header-files confirms my suspicion that the header-files are indeed incuded through the STL files.
// The header files that should be included for using the CrtDumpMemoryLeaks:
//#define _CRTDBG_MAP_ALLOC
//#include <stdlib.h>
//#include <crtdbg.h>
//...
_CrtDumpMemoryLeaks()
Leaving aside wether it's a good idea or not to implement my own new/delete, I am wondering how I can have my own new/delete implementations while still using some standard library functionality and not having these redefinition errors.
The code looks like this:
#ifndef _MEM_DEBUG_H
#define _MEM_DEBUG_H
#ifdef _DEBUG
void * operator new( unsigned int size, const char *filename, int line );
void operator delete( void *ptr );
#define DEBUG_NEW new(__FILE__, __LINE__)
#define new DEBUG_NEW
#endif
#endif
#ifdef _DEBUG
void * operator new( unsigned int size, const char *filename, int line )
{
void *ptr = (void *)malloc(size);
//AddTrack((DWORD)ptr, size, filename, line);
return(ptr);
};
void operator delete( void *ptr )
{
//RemoveTrack( (DWORD)ptr );
free( ptr );
}
#endif
#include "memdebug.h"
#include <iostream>
void main()
{
Test *pTest = new Test();
std::cout << "end" << std::endl;
}
The way I solved it is by moving the #define new DEBUG_NEW
below the <iostream>
;
The problem is resolved, since it won't rewrite the new in the crtdbg.h
; however this really makes it troublesome having to make sure that this is always being done after possible headers that include the crtdbg.h
file.
I believe this can only be resolved by using a custom name for the new operator and use that one instead. Am I correct?
Allright, the way I solved it for now, without having to use a custom 'new' define is that I've made a generic header file, let's say 'Engine.h' that is included in every file. This can be enforced by using the Forced Include File in the Project Settings / Configuration Properties / C/C++ / Advanced.
This file contains the #define (removed from the memdebug.h)
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <windows.h>
#include "MemoryNappy.h"
#define DEBUG_NEW new(__FILE__, __LINE__)
#define new DEBUG_NEW
This enforces the system to consider the crtdbg.h before the custom new-define and won't be changing the new there. The second time it's included somewhere down the line, it's just using the data that has already been loaded before. (In the case of including <iostream>
after the include of "engine.h"
).
Please note that overriding the new operator is still risky business when using third party libraries that might do the same trick. This causes the new operator for those files to be rewritten using the pattern used here. In that case you might want to reconsider the usage of a custom new define as in this fragment:
#define myNew new(__FILE__, __LINE__)
(Also described in http://www.flipcode.com/archives/Detecting_Memory_Leaks.shtml)