Tracking memory leaks in C++

Started by
33 comments, last by RobTheBloke 16 years, 8 months ago
Quote:Original post by Evil Steve
My memory manager; Overloads operators new and delete, has some stack walking functions to determine where allocations came from, is thread safe, and works with X64:
PMemory.h, PMemory.cpp.
That code won't compile straight out of the box, but it should with some minor modifications (E.g. removing my assert calls and so on). It should work with other compilers (untested), the only MSVC specific part I know of is the #pragma init_seg(compiler) call (Which is there to ensure the memory manager global is constructed before STL globals, so it can track STL "leaks").


Have you considered releasing the EvilSteve standard library so we can all easily accumulate all the code you've posted? [grin]
Advertisement
Quote:Original post by fpsgamer
That method is somewhat problematic. Consider the fact that you may have pointers that last for the entire life of the application. You do not have to bother deleting these since all memory your application claims during execution is returned to the system after termination anyways.

A memory leak involves you "losing handles" to memory during execution

ie.

int* a = new int[100];
a = (int*)5; // how the hell do we access our array now?

Now that memory is now lost for the entire execution of the application.

Using a more advanced tool will give you information about which pointers have not been free'd, not just that some stuff hasn't been free'd.


But isn't it still good practice to clean up all your memory resources when the program terminates? I'm just a novice, so you probably know more about it than I do :)

I don't doubt that an advanced tool would be useful (especially for a large-scale game). But rather than downloading a whole framework for my little projects, I'd rather just try to use good programming practice. Every time I make an allocation, I usually go down right away and put a free somewhere. Granted, this won't prevent the error you described (setting the pointer to a new value), but it can prevent memory leaks, say, when a pointer variable goes out of scope. My point is, there are ways of programming that can minimize the risks of memory leaks.
Quote:Original post by UltimateWalrus
But isn't it still good practice to clean up all your memory resources when the program terminates? I'm just a novice, so you probably know more about it than I do :)
Yup, definitely.

Quote:Original post by UltimateWalrus
My point is, there are ways of programming that can minimize the risks of memory leaks.
Minimise, yes. Remove, no. This is just one cause of a memory leak, there's loads of other things that can cause them.
Quote:Original post by UltimateWalrus
Quote:Original post by fpsgamer
That method is somewhat problematic. Consider the fact that you may have pointers that last for the entire life of the application. You do not have to bother deleting these since all memory your application claims during execution is returned to the system after termination anyways.

A memory leak involves you "losing handles" to memory during execution

ie.

int* a = new int[100];
a = (int*)5; // how the hell do we access our array now?

Now that memory is now lost for the entire execution of the application.

Using a more advanced tool will give you information about which pointers have not been free'd, not just that some stuff hasn't been free'd.


But isn't it still good practice to clean up all your memory resources when the program terminates? I'm just a novice, so you probably know more about it than I do :)

I don't doubt that an advanced tool would be useful (especially for a large-scale game). But rather than downloading a whole framework for my little projects, I'd rather just try to use good programming practice. Every time I make an allocation, I usually go down right away and put a free somewhere. Granted, this won't prevent the error you described (setting the pointer to a new value), but it can prevent memory leaks, say, when a pointer variable goes out of scope. My point is, there are ways of programming that can minimize the risks of memory leaks.


Ya, I think my phrasing was a little strong.

That method isn't as bad an I may have made it sound.
Quote:Original post by UltimateWalrus
I don't doubt that an advanced tool would be useful (especially for a large-scale game). But rather than downloading a whole framework for my little projects,


Paul Nettle's is easy and consists of two (well, three) files. Evil Steve's (obviously) consists of just two files. It's worth it [smile]
my_life:          nop          jmp my_life
[ Keep track of your TDD cycle using "The Death Star" ] [ Verge Video Editor Support Forums ] [ Principles of Verg-o-nomics ] [ "t00t-orials" ]
Quote:Original post by Evil Steve
My memory manager; Overloads operators new and delete, has some stack walking functions to determine where allocations came from, is thread safe, and works with X64:
PMemory.h, PMemory.cpp.
That code won't compile straight out of the box, but it should with some minor modifications (E.g. removing my assert calls and so on). It should work with other compilers (untested), the only MSVC specific part I know of is the #pragma init_seg(compiler) call (Which is there to ensure the memory manager global is constructed before STL globals, so it can track STL "leaks").


You could wrap that #pragma in a #ifdef or simular to make it only included in MSVC compilers? I haven't looked at your code but might be an idea. Just for your sake later too?

"Those who would give up essential liberty to purchase a little temporary safety deserve neither liberty nor safety." --Benjamin Franklin

If you're absolutely worried about memory leaks, use vector's contiguous memory layout. Deconstructor takes care of memory release, removing the need for pointer-based arrays.

When allocating/instantiating a single object through a pointer though, the extra memory and speed requirement of the vector class may not be worth it.

Also, one could build a registration class which tracks memory allocation through pointers by exposing member functions that are used in proxy of direct calls to new/new[] and delete/delete[]. This way the member function can examine the existing state of the pointer in question, and deallocate it if need be before allocating.

#include <iostream>using std::cout;using std::endl;#include <new>using std::nothrow;template<class T>bool array_alloc(T *&ptr, size_t elems = 0){	// T **ptr_to is used to compare against the database.	// Memory cost of tracking this pointer in the database	// is sizeof(T**).	T **ptr_to = &ptr;	bool is_allocated = false;	if(0 == elems)		return is_allocated; // false	// If this address is found in the database,	// it is passed to delete[].	if(0 != *ptr_to)		delete [] *ptr_to;	// Upon failure, return 0 instead of throwing std::bad_alloc.	*ptr_to = new(nothrow) T[elems*sizeof(T)];	if(0 == *ptr_to)		return is_allocated; // false;	else		is_allocated = true;	for(size_t i = 0; i < elems; i++)		(*ptr_to) = 0;	return is_allocated; // true}int main(void){	size_t size = 10;	char *y = 0;	array_alloc(y, size);	cout << static_cast<int>(y[size - 1]) << endl;		// When the database class goes out of scope,	// all known allocated pointers are passed to delete[].	return 0;}


Edit: changed the source.

[Edited by - taby on August 5, 2007 11:57:23 PM]
Quote:Original post by Zahlman
Or, just don't create memory leaks. :)


I wish it was that simple life would be great :P

I just spent the last three weeks writing custom software to track memory leaks and you'd be suprised on how many different ways you can leak memory.

The solution I've come up with is hook into new/placement new/malloc and your OS's allocation calls. Then write a function to walk up the stack, and based on the program counter look up the function name in the map file for the executable. This has given me the quickest way to track down memory leaks.

-= Dave
Graphics Programmer - Ready At Dawn Studios
If you are using MSVC you can also use Visual Leak Detector (http://dmoulding.googlepages.com/vld). It's very easy to use and the least intrusive method I have seen. It only works in debug mode, however.
If you're having trouble with memory, maybe consider a different design methodology for your new programs that naturally enforce memory construction/destruction rules. Each time I create a new class I write a standard set of functions that are called on construction and destruction of the class, it works very well.

Failing that, if you're considering overload the memory allocation functions, you may as well go the whole journey and create your own simple memory manager, that way you can be exceptional messy when allocating memory and just delete your memory manager pool at the end of the program. I personal think this is a brillant way of creating prototypes really quickly when you don't want to think about memory management.
http://www.fotofill.co.uk

This topic is closed to new replies.

Advertisement