Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

memory manager to prevent memory leaks

78 views
Skip to first unread message

hbdev...@gmail.com

unread,
Jan 17, 2014, 5:49:25 PM1/17/14
to
Hello,

I have written a memory tracker to prevent memory leaks in my programs.
The memory tracker meets the following requirements:
r1-Allocate memory using the system's new/new[].
r2-Deallocate memory using the system's delete/delete[].
r3-Log the file name and line where an allocation happens.
r4-When a memory is fred, remove the memory allocation from the log.
r5-At application exit, display the log.

Please find the code at the end of the email.
I have the following questions :

1-
g++ issues the following warning in my operator delete/delete[]: memtracker4.cpp:24:9: warning: deleting ‘void*’ is undefined [enabled by default]
delete p;
^
Do you have any idea how to correct the code so I don't get the warning ?

2-
To remove tracks of memory added in my operator new/new[], I am using template functions deleteArray and deleteObj.
But I remember in one company I worked in, they were using new(__FILE__,__LINE__) or new[](__FILE__,__LINE__) for allocations and plain delete/delete[] for deallocation.
And I wonder now, how they were removing memory tracks added by their operator new/new[] since they were using plain delete or delete[] for deallocation.
Could anybody please tell me if this is possible ? or were they not removing tracks ?

3-
Please tell me anything else to improve this code.

/////// code ////////

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

void AddToLog(long ptr, size_t size,const char * filename, int line)
{
printf("allocation : 0x%08X,%d,%s,%d\n",ptr, size,filename, line);
}

void RemoveFromLog(long ptr)
{
printf("deallocation : 0x%08X\n",ptr);
}

void * operator new(size_t size, const char *filename, int line)
{
void *ptr = ::operator new(size);
AddToLog((long)ptr, size, filename, line);
return(ptr);
};

void * operator new[](size_t size, const char *filename, int line)
{
void *ptr = ::operator new[](size);
AddToLog((long)ptr, size, filename, line);
return(ptr);
};

void operator delete(void *p, const char *filename, int line)
{
RemoveFromLog((long)p);
delete p; //g++ outputs warning: deleting ‘void*’ is undefined [enabled by default]
};

void operator delete[](void *p, const char *filename, int line)
{
RemoveFromLog((long)p);
delete [] p; //g++ outputs warning: deleting ‘void*’ is undefined [enabled by default]
};


template<class T> void deleteObj(T *p)
{
RemoveFromLog((long)p);
delete p;
};

template<class T> void deleteArray(T *p)
{
RemoveFromLog((long)p - sizeof(unsigned int));
delete [] p;
};


struct O11
{
int x;
public:
~O11 (){}
};

#define new new(__FILE__,__LINE__)

int main()
{
char *c=new char;
deleteObj<char>(c);

O11 *o=new O11;
deleteObj<O11>(o);

O11 *o1=new O11[10];
deleteArray<O11>(o1);

char *c3=new char[3];
deleteObj<char>(c3);
/*Note that I am treating c3 as a simple object not as array
(which caused my question at http://stackoverflow.com/questions/21178252/c-book-detailing-delete-and-delete)
*/

return 0;
}

Paavo Helde

unread,
Jan 18, 2014, 2:34:07 AM1/18/14
to
hbdev...@gmail.com wrote in
news:db61afcf-75c0-4f17...@googlegroups.com:

> Hello,
>
> I have written a memory tracker to prevent memory leaks in my
> programs.

This kind of memory tracker does not prevent leaks; at best it just
reports them, and *only in the executed code paths* which happen to be
passed during the run.

However, in C++ actually *preventing* memory leaks is usually simple,
just don't ever use new/delete (or malloc/free) in the application code.
Use automated classes like std::vector instead. If really needed,
encapsulate new/delete in a specific RAII class.

This avoids simple 'forgot-to-delete' errors, so any memory leaks can
come only from more complex logic errors in the program like accumulating
objects in some unbounded container or creating cyclic dependencies.

Anyway, when you don't have new/delete on the application level code any
more, you will notice that the __FILE__ and __LINE__ locations injected
by your 'new' macro do not give much useful information, if any. You will
want more deep call stacks instead (which are indeed provided by proper
memory debugging tools like valgrind).

So, as this memory tracker is both unreliable, subfunctional and most
often not needed, I would advise to ditch it and turn your efforts
instead of getting rid of new/delete in your code. For dealing with
remaining supposedly rare memory problems I would suggest to use existing
special tools like valgrind.


> The memory tracker meets the following requirements:
> r1-Allocate memory using the system's new/new[].
> r2-Deallocate memory using the system's delete/delete[].
> r3-Log the file name and line where an allocation happens.
> r4-When a memory is fred, remove the memory allocation from the log.
> r5-At application exit, display the log.
>
> Please find the code at the end of the email.
> I have the following questions :
>
> 1-
> g++ issues the following warning in my operator delete/delete[]:
> memtracker4.cpp:24:9: warning: deleting ‘void*’ is undefined [enabled
> by default]
> delete p;
> ^
> Do you have any idea how to correct the code so I don't get the
> warning ?

This should be something like ::operator delete [](p); instead.

>
> 2-
> To remove tracks of memory added in my operator new/new[], I am using
> template functions deleteArray and deleteObj. But I remember in one
> company I worked in, they were using new(__FILE__,__LINE__) or
> new[](__FILE__,__LINE__) for allocations and plain delete/delete[]
> for deallocation. And I wonder now, how they were removing memory
> tracks added by their operator new/new[] since they were using plain
> delete or delete[] for deallocation. Could anybody please tell me if
> this is possible ? or were they not removing tracks ?

Why would you need __FILE__ and __LINE__ of the point of deletion if you
will remove the allocation entry anyway?

hth
Paavo

Nick Baumbach

unread,
Jan 18, 2014, 3:45:15 AM1/18/14
to
Paavo Helde wrote

> However, in C++ actually *preventing* memory leaks is usually simple,
> just don't ever use new/delete (or malloc/free) in the application code.
> Use automated classes like std::vector instead. If really needed,
> encapsulate new/delete in a specific RAII class.

How does Boost implement dynamic memory allocation?

Jorgen Grahn

unread,
Jan 18, 2014, 12:46:55 PM1/18/14
to
On Sat, 2014-01-18, Paavo Helde wrote:
> hbdev...@gmail.com wrote in
> news:db61afcf-75c0-4f17...@googlegroups.com:
>
>> Hello,
>>
>> I have written a memory tracker to prevent memory leaks in my
>> programs.
>
> This kind of memory tracker does not prevent leaks; at best it just
> reports them, and *only in the executed code paths* which happen to be
> passed during the run.
...
(reordered a bit)
> So, as this memory tracker is both unreliable, subfunctional and most
> often not needed, I would advise to ditch it and ...

That's a bit harsh ...

> However, in C++ actually *preventing* memory leaks is usually simple,
> just don't ever use new/delete (or malloc/free) in the application code.
> Use automated classes like std::vector instead. If really needed,
> encapsulate new/delete in a specific RAII class.

I agree to that, and I personally have had no or very few resource
leaks in my C++ code in recent years.

But I'm always suspicious about advice which assumes:
- you work only with people who produce good C++ code
- you do so yourself
- you always have spare time to go back and rewrite code
which turned out bad.

There's nothing wrong with tools which help you deal with imperfect
code. C++ itself is such a tool!

My advise would be slightly different:
- There are many tools which do this already; use some of
those. (The ones which work with C's malloc/free should work
for C++ code too.)
- If you use them and find leaks, think about how you could
have used the language to make them impossible or unlikely.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

hbdev...@gmail.com

unread,
Jan 18, 2014, 3:04:40 PM1/18/14
to
On Saturday, January 18, 2014 2:34:07 AM UTC-5, Paavo Helde wrote:


>
> Why would you need __FILE__ and __LINE__ of the point of deletion if you
> will remove the allocation entry anyway?
>
This is because the compiler asks for a matching operator delete for each operator new I overload.

Thank you very much for your constructive reaction

hbdev...@gmail.com

unread,
Jan 18, 2014, 3:05:46 PM1/18/14
to

Thank you very much for your constructive reaction Jorgen Grahn

Paavo Helde

unread,
Jan 18, 2014, 4:14:25 PM1/18/14
to
hbdev...@gmail.com wrote in
news:8612e686-dd66-4714...@googlegroups.com:

> On Saturday, January 18, 2014 2:34:07 AM UTC-5, Paavo Helde wrote:
>
>
>>
>> Why would you need __FILE__ and __LINE__ of the point of deletion if
>> you will remove the allocation entry anyway?
>>
> This is because the compiler asks for a matching operator delete for
> each operator new I overload.

This is used only for automatic release of memory in case the object
creation fails (constructor throws an exception). One cannot call the
placement delete operator directly (there is no syntax for passing the
'placement' parameters in the delete-expression).

So, in your leak detector you probably should redefine the standard
operator delete as well, to avoid the cumbersome deleteObj() function (and
probably switch to using malloc/free for the actual memory allocation, to
avoid infinite recursion problems).

hth
Paavo
0 new messages