Macro needed

Y

Yogesh

Hi List,
I am overloading new and delete globally for memory leak detection.

void* operator new(std::size_t s, const char * file , int inLine) ;
->case1
void* operator new[](std::size_t s, const char * file , int inLine);
->case 2

I implement the above two functions using malloc. Now to replace all
occurances of
standard new with my above new operator I use the below macro.


#define DEBUG_NEW new(__FILE__, __LINE__)
#define new DEBUG_NEW

This works for first case.
My question is can I define a Macro in a similar way for second case
also?
if so, how?
if not, any work around to replace all occurances of operator new[]
with my operator?
 
V

Victor Bazarov

Yogesh said:
I am overloading new and delete globally for memory leak detection.

void* operator new(std::size_t s, const char * file , int inLine) ;
->case1
void* operator new[](std::size_t s, const char * file , int inLine);
->case 2

I implement the above two functions using malloc. Now to replace all
occurances of
standard new with my above new operator I use the below macro.


#define DEBUG_NEW new(__FILE__, __LINE__)
#define new DEBUG_NEW

This works for first case.
My question is can I define a Macro in a similar way for second case
also?

Doesn't it work for the second case as well?
if so, how?
if not, any work around to replace all occurances of operator new[]
with my operator?

Uh... I am sorry, I probably don't understand the problem. If you
have

int * pi = new int(666);

you now get

int * pi = new("somefile.cc", 42) int(666);

, right? So, if you have to allocate an array,

int * parr = new int[666];

would it just as well be

int * parr = new("somefile.cc", 42) int[666];

??? What's different about 'new[]'? Or were you just afraid to try?

V
 
M

mlimber

Yogesh said:
Hi List,
I am overloading new and delete globally for memory leak detection.

void* operator new(std::size_t s, const char * file , int inLine) ;
->case1
void* operator new[](std::size_t s, const char * file , int inLine);
->case 2

I implement the above two functions using malloc. Now to replace all
occurances of
standard new with my above new operator I use the below macro.


#define DEBUG_NEW new(__FILE__, __LINE__)
#define new DEBUG_NEW

This works for first case.
My question is can I define a Macro in a similar way for second case
also?
if so, how?
if not, any work around to replace all occurances of operator new[]
with my operator?

If we ignore the bigger problem, I think your #defines would work for
both new and new[] since you'd invoke it like this:

int *ptr = new int(42);
int *array = new int[ 100 ];

With your macros, these would become

int *ptr = new("MyFile.cpp", 10) int(42);
int *array = new("MyFile.cpp", 11) int[ 100 ];

However, let me suggest that your approach of using __FILE__ and
__LINE__ won't work. See this recent discussion for details:

http://groups.google.com/group/comp.lang.c++/browse_frm/thread/d1011b4e2c8e4be6

Consider using an existing library for your platform to look for leaks,
rather than writing your own. (Google for them.) Also, the thorough use
of smart pointers (e.g., std::auto_ptr, boost::scoped_ptr, and
boost::shared_ptr) virtually eliminates the possibility of memory
leaks. Consider using such practices.

Cheers! --M
 
Y

Yogesh

Hi ,
Thanks for prompt reply.
I was not aware that though "new" and "new[]" are different operators,
they are
translated in the same(similar) way by the compiler.
Consider using an existing library for your platform to look for leaks,
rather than writing your own. (Google for them.) Also, the thorough use
of smart pointers (e.g., std::auto_ptr, boost::scoped_ptr, and
boost::shared_ptr) virtually eliminates the possibility of memory
leaks. Consider using such practices.

I am looking into existing code, so replacing normal pointers with
std::auto_ptr,
boost::scoped_ptr is tedious job. Also I felt it would be a good
experience to do
it myself, than using a existing tool.

However, let me suggest that your approach of using __FILE__ and
__LINE__ won't work. See this recent discussion for details:

Dont know, why you say that. Please look at the code below. It seems to
work fine.
Mac OSX 10.4.2, gcc 4.0.1(Xcode)

Let me know if I am doing something wrong.
I call void "PrintMemoryDump()" at application Shutdown.

---------------------------------MemoryTest.h(Begin)--------------------------------------------------

#ifndef _MEMORY_TEST_H_
#define _MEMORY_TEST_H_

#include <new>
#include <stdio.h>
#include <stdlib.h>

void* operator new(std::size_t s, const char * file , int inLine) ;
void operator delete(void*) throw();

void* operator new[](std::size_t s, const char * file , int inLine);
void operator delete[](void*) throw();

void PrintMemoryDump();

#define DEBUG_NEW new(__FILE__, __LINE__)
#define new DEBUG_NEW

#endif

---------------------------------MemoryTest.h(End)--------------------------------------------------



---------------------------------MemoryTest.cpp(Begin)--------------------------------------------------
#include "MemoryTest.h"


#ifdef DEBUG_NEW
#define DEBUG_NEW new
#endif

struct tMemoryBlock
{
char _file[256];
int _lineNumber, _numBytes;
void * _pointer;
bool _deleted;
tMemoryBlock * next;
};

tMemoryBlock* head = NULL;

void AddBlock(tMemoryBlock ** inBlock)
{
if(head == NULL)
{
head = *inBlock;
return;
}
tMemoryBlock * ptr = head;
while(ptr ->next != NULL)
{
ptr = ptr->next;
}
ptr ->next = *inBlock;
}

void RemoveBlock(void * inptr)
{
if(head == NULL) return;
tMemoryBlock * ptr = head;
while(ptr != NULL)
{
if(ptr->_pointer == inptr)
{
ptr->_deleted = true;
}
ptr = ptr->next;
}
}

void PrintMemoryDump()
{
tMemoryBlock * ptr = head;
while(ptr != NULL)
{
if(ptr->_deleted == false)
{
fprintf(stderr, "**MEM LEAK** %s %d\n",ptr->_file,ptr->_lineNumber);
}
ptr =ptr->next;
}
ptr = head->next; tMemoryBlock * dptr= head;

while(ptr != NULL)
{
free(dptr);
dptr = ptr;
ptr = ptr->next;
}
}

void* operator new(std::size_t s, const char * file , int inLine)
{
void *ptr = (void *)malloc(s);
tMemoryBlock * t = (tMemoryBlock*)malloc(sizeof(tMemoryBlock));
strcpy(t->_file, file);
t->_lineNumber = inLine;
t->_deleted = false;
t->_numBytes = s;
t->next = NULL;
t->_pointer = ptr;

AddBlock(&t);

return(ptr);
}

void operator delete(void* p) throw()
{
RemoveBlock(p);
free(p);
}

void* operator new[](std::size_t s, const char * file , int inLine)
{

void *ptr = (void *)malloc(s);
tMemoryBlock * t = (tMemoryBlock*)malloc(sizeof(tMemoryBlock));
strcpy(t->_file, file);
t->_lineNumber = inLine;
t->_deleted = false;
t->_numBytes = s;
t->next = NULL;
t->_pointer = ptr;

AddBlock(&t);
return(ptr);
}

void operator delete[](void*p) throw()
{
RemoveBlock(p);
free(p);
}

#define new DEBUG_NEW
#define DEBUG_NEW new(__FILE__, __LINE__)


---------------------------------MemoryTest.cpp(End)--------------------------------------------------
 
M

mlimber

Yogesh said:
I am looking into existing code, so replacing normal pointers with
std::auto_ptr,
boost::scoped_ptr is tedious job. Also I felt it would be a good
experience to do
it myself, than using a existing tool.

It would likely be a good learning exercise, and I commend it to you
for your edification. However, if this is for production code, I would
suggest using an existing library since there are can be quite a few
subtleties involved. (For similar reasons, Bjarne Stroustrup recommends
in TC++PL 6.2.6.2 that anyone wishing to implement a garbage collector
except as an educational exercise should get one that has already been
written and tested.)
However, let me suggest that your approach of using __FILE__ and
__LINE__ won't work. See this recent discussion for details:

Dont know, why you say that. Please look at the code below. It seems to
work fine.
Mac OSX 10.4.2, gcc 4.0.1(Xcode)

Let me know if I am doing something wrong.
I call void "PrintMemoryDump()" at application Shutdown.

---------------------------------MemoryTest.h(Begin)--------------------------------------------------

#ifndef _MEMORY_TEST_H_
#define _MEMORY_TEST_H_

#include <new>
#include <stdio.h>
#include <stdlib.h>

void* operator new(std::size_t s, const char * file , int inLine) ;
void operator delete(void*) throw();

void* operator new[](std::size_t s, const char * file , int inLine);
void operator delete[](void*) throw();

void PrintMemoryDump();

#define DEBUG_NEW new(__FILE__, __LINE__)
#define new DEBUG_NEW

#endif

---------------------------------MemoryTest.h(End)--------------------------------------------------

[code snipped]

One of the subtleties that I have in mind is that, when new fails (e.g.
if a constructor throws an exception), the compiler implicitly looks
for a corresponding delete operator with a similar signature to the
new, but you have not provided such an operator, which means you would
have a very tricky memory leak. See this FAQ:

http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.14

which describes what happens behind the scenes when you call new. Note
particularly its "Problem #1". (The FAQ discusses placement new, which
is similar to your "new with parameter" usage here.)

In any case, I was assuming that you were using the filename/line to be
the block lookup key, which you are not. So you've already avoided one
danger present in the previously cited thread.

BTW, I only looked cursorily at your code, but I did notice that
AddBlock() doesn't need a double pointer passed in.

Cheers! --M
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,069
Latest member
SimplyleanKetoReviews

Latest Threads

Top