简体   繁体   中英

Override new operator in C++ while crtdbg.h is causing conflicts

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:

memdebug.h

#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

memdebug.c

#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

main.cpp

#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)

engine.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 )

In one application of ours we resorted to renaming everywhere at the application level new with xnew and then defining the debug macro as acting only on xnew .

Using new and redefining it as a macro can have problems also with custom allocators. Unfortunately C++ syntax for allocation made debugging wrappers harder to do.

On Visual Studio 2010, I was able to do this without redefinition of new or custom defined new. I created a header file with the following:

#pragma once
//_CRTDBG_MAP_ALLOC
//_CRTDBG_MAP_ALLOC_NEW
#define _CRTDBG_MAP_ALLOC
#define _CRTDBG_MAP_ALLOC_NEW
#include <stdlib.h>
#include <crtdbg.h>

and forced its inclusion on every source file, with the already discussed option Forced Include File , in the Project Settings / Configuration Properties / C/C++ / Advanced . Actually, crtdbg.h already do this custom definition of new , along with undefinition of regular new . And just to make sure everything would run smoothy, I added _CRTDBG_MAP_ALLOC and_CRTDBG_MAP_ALLOC_NEW to Preprocessor Definition list, available in: Project Settings / Configuration Properties / C/C++ / Preprocessor .

Hope this will help on this issue.

Try _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); -- as described in my blog post , no new redefinition needed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM