2

I'm currently working on my own memory leak tracking system.

I'm using Microsoft Visual C++ 2008 and I know they have a built in one, but I've been making one for myself, just for the fun of it.

However, when I override the new and new[] commands, I get a function redefinition error, no matter what I do.

I don't know much about Microsoft Visual C++'s internal bindings on things, but I've heard it is something with the CRT already defining the exact same macro I am.

I've seen articles on here and other places directed at this same exact question, but people can never seem to solve the problem or never give a definite answer on how they solved it.

Here is all the code I have up till this point:

MLD.h : http://pastebin.com/SfHzNaeN MLD.cpp : http://pastebin.com/aRhsTZpv

All of the code is loosely based off a old flipcode article (How To Detect Memory Leaks). Sorry I cannot give you a direct link, because I don't have 10 rep to post more than 2 hyperlinks.

Thanks for your time.

Unknown
  • 23
  • 2
  • Were you referring to [this](http://www.flipcode.com/archives/How_To_Find_Memory_Leaks.shtml) article? – Hindol May 20 '12 at 15:01
  • Indeed I was, thank you. – Unknown May 20 '12 at 16:06
  • Have you read: [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 May 20 '12 at 18:34
  • I applied those things just now, because they seem to be a decent addition. However, have any of you solved this problem in anyway? I cannot seem to get Visual C++ to stop calling function redefinition. – Unknown May 20 '12 at 19:28

1 Answers1

2

The “function redefinition error” is probably because you’re using MFC.

The runtime library should not be in the business of defining such allocation and deallocation functions.

The current code’s

struct MemLeakInfo
{
        unsigned int addr;
        unsigned int line;
        unsigned int size;
        unsigned char file;
};

is ungood. An unsigned int is not guaranteed to be large enough to hold an address, even though it is in 32-bit Windows. Instead, use intptr_t.

Also, the current code’s

void* operator new(unsigned int Size, int Line, const char* File);

is ungood. That should be …

void* operator new( size_t Size, int Line, const char* File );

And you need a corresponding operator delete, like …

void* operator delete( void* p, int Line, const char* File );

in order to deallocate memory from a failed constructor call. It's only called in that very specific situation. But if you don’t have it, then you have a leak, as MFC once had for debug builds.


EDIT: fixed versions of the code you now provided:

file [minimal.h]:

  • _MINIMAL_H is invalid, because it starts with underscore followed by uppercase letter, which is reserved. Changed to MINIMAL_H.
  • to use size_t you need to include <stddef.h>.
  • _DEBUG is not a standard macro. it's a microsoftism. the standard macro (look up documentation of assert) for this purpose is NDEBUG.

 

#ifndef MINIMAL_H
#define MINIMAL_H

#include <stddef.h>     // std::size_t

#ifndef NDEBUG

void* operator new( size_t Size, int Line, const char* File );
void* operator new[]( size_t Size, int Line, const char* File );

void operator delete( void* ptr, int Line, const char* File );
void operator delete[]( void* ptr, int Line, const char* File ); 

#endif 

#ifndef NDEBUG

#define DEBUG_NEW new( __LINE__, __FILE__ )

#else

#define DEBUG_NEW new

#endif 

#endif //MINIMAL_H

file [minimal.cpp]:

  • to use malloc you need to include stdlib.h.
  • when you #define new you’re wreaking havoc with the new keywords in the following code.
  • in C you should never cast the result of malloc, and in C++ you should only cast something when there is a need for it. there is no such need here. casts only mask bugs, and that's not a good idea.
  • missing return in error case. for error you need to throw std::bad_alloc. that's by the holy standard’s specification of these functions.

 

#include "Minimal.h"

//#define new DEBUG_NEW

#ifndef NDEBUG
#include <stdlib.h>     // malloc
#include <exception>    // std::bad_alloc

void* operator new( size_t const size, int, const char*)
{
    void* const ptr = malloc( size );

    if( !ptr ) { throw std::bad_alloc(); }
    return ptr;
};

void* operator new[]( size_t const size, int, const char*)
{
    void* const ptr = malloc( size );

    if( !ptr ) { throw std::bad_alloc(); }
    return ptr;
}

void operator delete(void* const ptr, int, const char*)
{
    free( ptr ); 
};

void operator delete[]( void* const ptr, int, const char* )
{
    free( ptr ); 
}; 

#endif
Community
  • 1
  • 1
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • Thanks for the extra information, I assumed unsigned int would be large enough for a address and if you don't mind me asking, why does delete actually need the line and file input? I have delete searching for the address with "RemoveMemoryInformation" and removing it from the STL vector and I'm not using MFC, that is why I've been trying to figure out what is causing such a collision. Thanks again. – Unknown May 20 '12 at 15:39
  • @Unknown: create a minimal but complete example that exhibits the problem. if that doesn't by itself tell you what the problem is, post that code. e.g. paste it on pastebin and post link here. – Cheers and hth. - Alf May 20 '12 at 16:10
  • the overloaded placement delete needs to have the same additional arguments as the corresponding placement new. that's how a new-expression knows to call it. the signature identifies it. – Cheers and hth. - Alf May 20 '12 at 16:11
  • http://pastebin.com/AFsNQqFS that is the minimal required code to reenact the problem. It is mostly just a constant "function redefinition" that pops up, when I'm not using MFC at all. – Unknown May 20 '12 at 16:23
  • Thank you very much, the #NDEBUG was exactly what I needed. Using it in stead of _DEBUG removed microsoft's collisions with mine. – Unknown May 21 '12 at 03:36