Jump to content

  • Log In with Google      Sign In   
  • Create Account

[С++] Memory leak checker


Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.


  • You cannot reply to this topic
24 replies to this topic

#1 AlexB.hpp   Members   -  Reputation: 201

Like
2Likes
Like

Posted 27 November 2012 - 04:42 PM

I've started working on simple and little class for C++ to check some memory leaks. I have made some work on it, but there is a lot of work to do. I'm planing to add cppunit, autoreconf, documentation, static class instread of global functions, different loggers.

Now it has:
shared library,
header with some funcs declarations,
makefile to build it via g++,
simple script to test it,
linux only but I'll port it to win after some researching.

I do it for my own project but I would like to share it with a great pleasure.

Now it looks like this
alexb leak_checker> ./run.sh
MEMORY LEAK! 0x8c1a008 main.cpp 5
MEMORY LEAK! 0x8c1a038 main.cpp 6

with such main:
#include <iostream>
#include "allocation_hooks.h"
int main(int argc, char** argv) {
  int* num = new int;
  num = new int[1];
  check_map();
}


Repo is here.

PS Warning it has some magic in it! ^_^

Edited by AlexB.hpp, 28 November 2012 - 08:00 AM.

C x 2 C x o C x C f nice C x C s C x C c

#2 ApochPiQ   Moderators   -  Reputation: 19915

Like
3Likes
Like

Posted 27 November 2012 - 04:49 PM

#include <malloc.h>

#include "allocation_hooks.h"



int main() {

    void* foo = malloc(1024);

    check_map();          // No leak reported.

}

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

#3 AlexB.hpp   Members   -  Reputation: 201

Like
0Likes
Like

Posted 27 November 2012 - 04:52 PM

#include <malloc.h>
#include "allocation_hooks.h"

int main() {
	void* foo = malloc(1024);
	check_map();		  // No leak reported.
}

Cause there is no malloc overloading. Will add to todo list. Thx

1st issue added.

Edited by AlexB.hpp, 27 November 2012 - 04:55 PM.

C x 2 C x o C x C f nice C x C s C x C c

#4 SiCrane   Moderators   -  Reputation: 11271

Like
4Likes
Like

Posted 27 November 2012 - 05:18 PM

Don't forget calloc() and realloc(). realloc() is always a fun one to deal with because depending on how you call it, it can also act like malloc() or free().

#5 AlexB.hpp   Members   -  Reputation: 201

Like
1Likes
Like

Posted 28 November 2012 - 02:48 AM

Don't forget calloc() and realloc(). realloc() is always a fun one to deal with because depending on how you call it, it can also act like malloc() or free().

Thx for calloc don't even know about it.
C x 2 C x o C x C f nice C x C s C x C c

#6 AlexB.hpp   Members   -  Reputation: 201

Like
0Likes
Like

Posted 28 November 2012 - 03:53 AM

Added malloc, calloc, realloc and free wrappers. Added gitignore.

I have a question about realloc. Does it reallocate of incoming pointer? Is it correct in my code?

Edited by AlexB.hpp, 28 November 2012 - 03:56 AM.

C x 2 C x o C x C f nice C x C s C x C c

#7 wqking   Members   -  Reputation: 756

Like
0Likes
Like

Posted 28 November 2012 - 04:02 AM

Good start.

But reporting leaks with only addresses is not quite helpful.
I would like to know the call stack and the class name, if possible.

http://www.cpgf.org/
cpgf library -- free C++ open source library for reflection, serialization, script binding, callbacks, and meta data for OpenGL Box2D, SFML and Irrlicht.
v1.5.5 was released. Now supports tween and timeline for ease animation.


#8 Memories are Better   Prime Members   -  Reputation: 769

Like
2Likes
Like

Posted 28 November 2012 - 05:31 AM

I forgotten the method (since this technique ironically reports smart pointers as leaks heh) but MFC has a pretty decent way of checking for leaks already even if you arent making MFC apps, heres the link anyway http://msdn.microsoft.com/en-us/library/c99kz476(v=vs.100).aspx

#9 AlexB.hpp   Members   -  Reputation: 201

Like
0Likes
Like

Posted 28 November 2012 - 07:27 AM

Good start. But reporting leaks with only addresses is not quite helpful. I would like to know the call stack and the class name, if possible.

I'm planning such output:
Memory leaks summary:
  operator new in main.cpp:34 (0x0fa43d41) allocated 4 bytes
  ...

What output would be enough informative for you?

I forgotten the method (since this technique ironically reports smart pointers as leaks heh) but MFC has a pretty decent way of checking for leaks already even if you arent making MFC apps, heres the link anyway http://msdn.microsoft.com/en-us/library/c99kz476(v=vs.100).aspx

I'm making it as cross-platform solution. But however thanks.
C x 2 C x o C x C f nice C x C s C x C c

#10 SiCrane   Moderators   -  Reputation: 11271

Like
2Likes
Like

Posted 28 November 2012 - 08:33 AM

Your realloc() implementation is definitely wrong. As it is, it creates a memory leak. If realloc() returns a new address, the old allocation needs to be freed. Also, the data copy doesn't properly handle the situation where the new size is greater than the old size.

#11 AlexB.hpp   Members   -  Reputation: 201

Like
0Likes
Like

Posted 28 November 2012 - 10:26 AM

Your realloc() implementation is definitely wrong. As it is, it creates a memory leak. If realloc() returns a new address, the old allocation needs to be freed. Also, the data copy doesn't properly handle the situation where the new size is greater than the old size.

Many thanks about this issue with old ptr.
Yeah I knew about greater size then old ptr had. Will it be ok if i'll do memset(new_ptr, 0, size)?
C x 2 C x o C x C f nice C x C s C x C c

#12 SiCrane   Moderators   -  Reputation: 11271

Like
1Likes
Like

Posted 28 November 2012 - 11:44 AM

Probably not, but I wouldn't know for sure unless I saw the complete context for your code. Either way it doesn't address the issue of properly copying the data in the buffer that realloc() is supposed to do.

#13 AlexB.hpp   Members   -  Reputation: 201

Like
0Likes
Like

Posted 28 November 2012 - 01:03 PM

Probably not, but I wouldn't know for sure unless I saw the complete context for your code. Either way it doesn't address the issue of properly copying the data in the buffer that realloc() is supposed to do.

To prevent all misunderstandings I've implemented it via original funcs.

Also I have improved output:
Memory leak summary:
	    operator new (0x83af008) missed 4 bytes in main.cpp:5
	    operator new[] (0x83af040) missed 4 bytes in main.cpp:6
	    malloc (0x83af078) missed 4 bytes in main.cpp:7
	    calloc (0x83af0b0) missed 4 bytes in main.cpp:8
	    realloc (0x83af0e8) missed 8 bytes in main.cpp:10
Total leaked 24 bytes

C x 2 C x o C x C f nice C x C s C x C c

#14 SiCrane   Moderators   -  Reputation: 11271

Like
1Likes
Like

Posted 28 November 2012 - 01:36 PM

That still doesn't handle realloc() properly. You aren't taking into account instances when size is equal to zero and you are also aren't handling null return values properly for what looks like any of the allocation functions. Your code also looks like it blows up messily if your header is included before code that uses placement new (which includes large chunks of the standard library).

#15 e‍dd   Members   -  Reputation: 2109

Like
3Likes
Like

Posted 28 November 2012 - 02:33 PM

Some other problems:
  • void* operator new[] is missing a 'return'.
  • Not exception safe (meaning that somewhat ironically, it can cause leaks).
  • Causes problems with existing placement-new overloads (though working around that is probably very tricky).


#16 AlexB.hpp   Members   -  Reputation: 201

Like
0Likes
Like

Posted 28 November 2012 - 02:49 PM

That still doesn't handle realloc() properly. You aren't taking into account instances when size is equal to zero and you are also aren't handling null return values properly for what looks like any of the allocation functions. Your code also looks like it blows up messily if your header is included before code that uses placement new (which includes large chunks of the standard library).

Hm. I've read it already. Tomorrow I'll fix it. That bastard is really tricky, too many behaviors for just one func...
About including my header - yeah it has a bug here, I know about it. I'll describe it in docs. Have no ideas now. Thank you.

Some other problems:

  • void* operator new[] is missing a 'return'.
  • Not exception safe (meaning that somewhat ironically, it can cause leaks).
  • Causes problems with existing placement-new overloads (though working around that is probably very tricky).

Many thanks. Still need some tests. It's in todo list.
About placement new... I'll keep it in mind.
C x 2 C x o C x C f nice C x C s C x C c

#17 SiCrane   Moderators   -  Reputation: 11271

Like
0Likes
Like

Posted 28 November 2012 - 07:09 PM

I told you that realloc() was a fun one to deal with. As for the placement new problems, there aren't a lot of good options when you're avoiding platform dependent code. One approach used in Paul Nettle's mmgr is to create a header that undefined the macros in the memory manager. So there were a pair of headers, both without header guards, that could be used to toggle on and off the macros so it wouldn't screw up third party headers. I'm not a big fan of this technique. It's annoyingly manual and has the possibility of introducing ODR errors. More importantly, the information from the macros isn't that useful by itself. Sure it's better than nothing, but I'd much have a stack trace to see not only where the leaked allocation was done, but what called the function that leaked the allocation and so on.

#18 Hodgman   Moderators   -  Reputation: 47796

Like
2Likes
Like

Posted 28 November 2012 - 08:45 PM

This isn't exactly helpful for the purposes of a general purpose leak-detector, so feel free to disregard Posted Image

The way that I've seen most engine code-bases deal with these issues, is to simply ban the use of standard allocation routines (new/malloc/etc) as part of their coding guidelines. The only 'new' that is allowed is placement-new, and it's probably never used directly, but via an engine macro.
If you want memory, you get it from the engine's allocation API, which becomes the single place where tracking code needs to be inserted.

#19 hupsilardee   Members   -  Reputation: 491

Like
0Likes
Like

Posted 29 November 2012 - 08:48 AM

This isn't exactly helpful for the purposes of a general purpose leak-detector, so feel free to disregard Posted Image

The way that I've seen most engine code-bases deal with these issues, is to simply ban the use of standard allocation routines (new/malloc/etc) as part of their coding guidelines. The only 'new' that is allowed is placement-new, and it's probably never used directly, but via an engine macro.
If you want memory, you get it from the engine's allocation API, which becomes the single place where tracking code needs to be inserted.


Or you could make as many objects as possible exist/allocated on the stack, maybe using 2 step initialisation, or use a factory pattern?

#20 Matias Goldberg   Crossbones+   -  Reputation: 7959

Like
1Likes
Like

Posted 29 November 2012 - 10:14 AM

Your system won't work (& may crash) if the application is allocating memory from multiple threads. Writing a scalable memory tracker that handles multiple threads is your next real challenge.

Edit: Also, you need to handle the nothrow variations of new & delete. There is a total of 4 news & 4 deletes to overload.

Edited by Matias Goldberg, 29 November 2012 - 10:15 AM.





Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.




PARTNERS