Archived

This topic is now archived and is closed to further replies.

Ratman

Fixing memory leaks

Recommended Posts

Aside from "not writing them in the first place" what is a good way to track down memory leaks? I have a feeling my program has a few, but have no idea where they are. Are there any tools/tricks/etc you guys use to track them down? or is it pretty much going through all your code and making sure you clean up everything? Thanks ratman

Share this post


Link to post
Share on other sites
There''s lots of software available you can use, such as Electric Fence, BoundsChecker, Purify, and so on. A search for memory leak detectors or whatever on a search engine should find some for you. They range from being freeware and open source to expensive applications. I used one called HeapAgent which is quite nice and had a (short) free trial. Annoyingly though, it had some sort of bug and stopped working properly after a few days. I talked to the tech support guy but he had no clue how to fix it. So I gave up, and certainly wouldn''t buy the product

Share this post


Link to post
Share on other sites
Purify and BoundsChecker are both great, and catch memory leaks as well as a bunch of other potential run-time problems. They cost a relative fortune though. Far more than most hobbiest developers can afford (hundreds to thousands of dollars).

I haven''t had any experience with the free programs/libraries, such as Electric Fence.

You can actually use Visual C++ to help you track down memory leaks or use a higher level memory management library in your projects. Check out some of the Code of the Days and older Ask Midnight''s on flipcode (http://www.flipcode.com) for specific information.

Share this post


Link to post
Share on other sites
MSVC 6 has an easy way to track memory leaks. Just include the following headers and put the next 3 lines in your startup or Winmain.

  
...at top of main file

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

...in winmain
int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); // Get current flag


flag |= _CRTDBG_LEAK_CHECK_DF; // Turn on leak-checking bit


_CrtSetDbgFlag(flag); // Set flag to the new value*/




Now do a debug build (F5) and at the end you will get a list of memory leaks. If you are using typical C malloc/free, it will give you the line and file the memory was allocated in. If you are using C++ new/delete on classes with constructors, it will tell you same line and file each time, but its better than nothing.

Share this post


Link to post
Share on other sites
To avoid memory leaks there are some basic rules you should follow:
- use STL (e.g. use std::string instead of char*, use std::vector instead of build in arrays like object[123][456])
- make shure you have a "delete" for every "new"
- keep your code as local as possible

You don''t have to do all this. But if you don''t want to have those little bas***** in your memory eating all of your memory and blocking it from other apps, try to use them.

Share this post


Link to post
Share on other sites
In C, you can just make functions to do all your allocating, and in C++ you can overload new/delete.

For example..

void* Malloc( int Size, int ReferenceID )
{
// Record in an array/list the ReferenceID and Size, and any other information you want to send
return malloc( Size );
}

void Free( void* AllocatedMemory, int ReferenceID )
{
// Remove the ReferenceID/Size from the array/list

free( AllocatedMemory );
}

When your program closes, check the list and output the results. This will help you track down where you''re allocating and not freeing.

Much more realistic than hobby developers buying hundreds of dollars software : )

G''luck,
-Alamar

Share this post


Link to post
Share on other sites
as mentioned above, there was a great tip-of-the-day about this at flipcode, check it out:

http://www.flipcode.com/cgi-bin/msg.cgi?showThread=Tip-DetectingMemoryLeaks&forum=totd&id=-1

Share this post


Link to post
Share on other sites
All these tools & tips are great, but I think there''s a problem more insidious than the bona-fide "leak" where memory is not deallocated before the program ends. We''ve had the unfortunate experience once or twice of using container that automatically grow without bounds and release memory once they''re destroyed. The problem is, if they''re really growing without bounds, you can overflow your memory and kill your system resources, even if you deallocate the memory at the end of the program --this does not show up in bounds checker or any "leak detection" utility.

This kind of memory behavior is best detected by running your program with a memory diagnostic tool running. WinNT comes with a great little tool called "Performance Monitor" which can attach to a process and show you handle counts, thread counts, memory allocations, CPU usage, etc. The built-in system monitor for Win98 isn''t adequate for this purpose, but I''m sure there''s some public-domain tools out there that will accomplish the same things. Basically, you want to run your program with this tool running, and if you see a straight slope upward on anything, you have a problem.

Share this post


Link to post
Share on other sites
quote:
Original post by Stoffel
We''ve had the unfortunate experience once or twice of using container that automatically grow without bounds and release memory once they''re destroyed. The problem is, if they''re really growing without bounds, you can overflow your memory and kill your system resources, even if you deallocate the memory at the end of the program --this does not show up in bounds checker or any "leak detection" utility.



Actually I believe you can do that with Midnight''s code (or by writing your own memory manager). It doesn''t just detect memory leaks, but also array bounds being overwritten, memory consumtion, etc, etc. Since all memory allocation must go through that code, you can generate stats on just about anything, including printing out the most memory consumed at any point the in program with which allocations consumed the most memory and the exact line of code that allocation took place. You may have to write a few new functions to do this, but it''s not hard.

Although I will conceed that Performance Monitor is a great tool. It allows you to quickly and easily see if certain memory problems exist, among other things, then you can use your own tools to track the problem down.


- Houdini

Share this post


Link to post
Share on other sites
One approach that''s worked well for me is to use an abstract allocator interface for all memory allocation, i.e. something with unimplemented methods for malloc, realloc, free, and so forth. The default implementation for this does nothing but punt down to the actual malloc/free/etc, but you can set it up to use other allocators for more extensive integrity checks, or other operations including leak tracking.

Some other leak-tracking methods are able to report the location of an allocation, but when you''re inside a small frequently-used function then it''s difficult to track down the real cause of the leak based on this information alone. A more descriptive call stack would provide this information, though, and Win32''s dbghelp functions like StackWalk, SymGetSymFromAddr, etc. are very useful for this. For my leak-tracking allocator, i do a stack walk for the most recent 8 calls on the stack, and store the addresses with the allocated memory block. Sure it''s an extra 32 bytes consumed per allocation, but it''s only necessary when you''re trying to track down leaks. The allocator also keeps track of all the allocated blocks in a doubly linked list (another 8 bytes per allocation, so it''s 40 bytes total). As blocks are allocated/freed, the linked list is modified accordingly. Finally, when I exit the application, the allocator dumps out all remaining blocks in the list, along with the call stack at the time of the allocation. Makes tracking down leaks *very* easy. I''ve seen this same idea mentioned recently in some postmortem in Game Developer magazine, and apparently it worked well for them too.

If you want to know more about StackWalk and the dbghelp library, take a look a Robbins'' excellent book "Debugging Applications". You can use this kind of functionality not only for tracking leaks, but also for assertions (as the author does), and even fatal exceptions, which is *very* handy for debugging. Just make sure if you''re using C++ and try/catch blocks that you grab the call stack before C++''s exception handling mechanism takes over... see the little-documented MSVC++ function _set_se_translator for a hint on doing this).

And note that all of this works in release builds as well as debug.

--
Chris Hargrove
Senior Programmer, Legend Entertainment

Share this post


Link to post
Share on other sites