Memory Leak detector

1 12 2010

When you are writing a program and you want it to be able to run for a long period of time or when some procedure is called a x times in the lifetime of running program (let x tend to infinity) maybe is a good opportunity to make sure all your malloc calls have one free call (new,delete in C++).This sounds very natural to any experienced programmer.

Now imagine that you have download some huge chunk of code and you want to call it x times, lets say 100 times per second. Maybe the person who wrote the code, did not think about memory management and maybe you do not have the patience to read the huge piece of code. What you need is a memory leak detector.

If you do not have any of these problems might be interested in knowing how to gain millions of euros on the internet.

Here I will show an example of how to write a simple memory leak detector in C++ for C (malloc,free), is trivial to convert it to verify memory leaks in C++.

The main idea is to keep the line number of each malloc we do and then verify if we did free, we will accomplish this by redefining the malloc and free call, without need to write our own free or malloc, thanks to C pre processor.

First we define an entity, this keep all the information we need about each malloc call.

class Entity {
private:
	unsigned int _address;
	unsigned int _line;
public:
	Entity(unsigned int addr, unsigned int line) {
		this->_address = addr;
		this->_line = line;
	}
	unsigned int & getOrSetAddress() {
		return this->_address;
	}
	unsigned int getLine() {
		return this->_line;
	}
};

typedef std::list<Entity *> Memory;
Memory *memory;

I used the standard C++ lists instead of std::vector because I will need to remove and add elements, without the need to call find in algorithms module, what bugs me.

Now I will define the function to add elements to our std::list

void InsertOnMalloc(unsigned int addr, unsigned int n) {
	if(!memory)
		memory = new Memory;

	memory->insert(memory->begin(), new Entity(addr,n));
}

Now I will define the function to remove elements to our std::list

void RemoveOnFree(unsigned int addr) {
	if(!memory)
		return;
	for(Memory::iterator it = memory->begin(); it != allocList->end(); it++)
	{
		Entity *entity = *it;
		if(entity->getOrSetAddress() == addr) {
			memory->remove();
			break;
		}
	}
}

The idea so far is to call InsertOnMalloc for each malloc call and RemoveOnFree for each free. After this if we have any element in our memory we need to print that out, to see which line we do not call free.

void ShowLeaks() {
	for(Memory::iterator it = memory->begin(); it != memory->end(); it++)
		std::cout << "Must make free to this malloc call: " << (*it)->getLine() << std::endl;
}

Now, lets do the real juice of this leak detector: here I will modify the malloc call to a regular malloc followed by an insertion, and a free call for a regular free call followed by removal on our memory list

#define malloc(p) mallocz((p),__LINE__)
#define free(p) freez((p))

static inline void *  mallocz(unsigned int size, int line) {
	#undef malloc
	void *ptr = (void *)malloc(size);
	#define malloc(p) mallocz((p),__LINE__)
	Insert((unsigned int)ptr, line);
	return(ptr);
};
static inline void  mydelz(void *p) {
	RemoveOnFree((int)p);
	#undef free
	free(p);
	#define free(p) freez((p))
};

Now, if you want to use this “library” in your code, you save it to file filename.h and on you code you just import it and then call ShowLeaks() to show what mallocs you forgot to make free.


Actions

Information

Leave a comment