Click here to Skip to main content
15,886,362 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a C++ application which contains a memory-leak, although I am using "Leakdiag" and "LDGrapher", I can't locate where the leak is?!
I'm also using "_CrtDumpMemoryLeaks()" function which give me results like this:
Detected memory leaks!
Dumping objects ->
{657} normal block at 0x00D93B98, 52 bytes long.
 Data: < N   N          > D8 4E D9 00 D8 4E D9 00 00 00 00 00 CD CD CD CD
{656} normal block at 0x00D93AF0, 108 bytes long.
 Data: <(        ;  (   > 28 F0 12 00 00 00 00 00 98 3B D9 00 28 F0 12 00
{655} normal block at 0x00D94ED8, 52 bytes long.
 Data: < ;   ;          > 98 3B D9 00 98 3B D9 00 CD CD CD CD CD CD CD CD
f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\occcont.cpp(923) : {641} normal block at 0x00D92100, 12 bytes long.
 Data: <            > F6 06 0A 00 00 00 00 00 00 00 00 00

How can I locate the real location of the memory leak?
Posted
Updated 31-May-12 1:27am
v2

The way I used, when confronted with a leak, was all manual - no tools.
The important thing is: you don't have to find the leak in order to fix it.
Look for malloc() calls (and friends: calloc, realloc, strdup): replace as many of them as possible by stack variables, and all the others by smart pointers (std::auto_ptr,. for instance). Wherever you keep a heap allocation, add a comment with a really good excuse: the maximum size of a buffer is not known until run time, or the function is actually a factory whose purpose is to allocate and initialize an object.
Look for places where new and delete are used as if they were malloc and free. Use std::auto_ptr instead.
Look for global pointers. Destroy them.

In the end you'll have not only fixed the leak, but you'll have improved overall code quality.

Just my two bits,
 
Share this answer
 
v2
Comments
Aescleal 1-Jun-12 6:46am    
While I agree with a lot of the advice here (and it's a lot better than most textbooks and lecturers give out) I would add:-

- never use std::auto_ptr. If that's all you've got then grab a copy of boost
- for variable sized buffers std::vector works pretty well
- immediately assign anything that has ownership transferred to your code to either std::unique_ptr or std::shared_ptr
The quickest way to avoid memory leaks is to not make them in the first place. There's really no reason to manually manage memory any more, it's a bit of a mug's game.

That said there are a few of things you can try without digging into the standard library source code (nv3 knows more than I do about the structure of the runtime heap):

- Find all the places you're using new. When you find them:-

(a) work out if the object can be stack allocated instead (Java programmers in particular are buggers for newing everything and not using RAII). If you can replace them with stack objects do so!

(b) replace any raw pointers that represent ownership with std::unique_ptr, std::shared_ptr or std::vector

(c) remove all the deletes that that the compiler is now complaining about

- Instrument new and delete. Make a memory block counter class which you can declare in scopes to see if a leak potentially occurs in there. Use it in your unit tests and it'll show up if an object is leaking a contained object.

- Instrument selected class's constructors and destructor. Select them by choosing ones that are about the same size as the blocks that are being lost. Keep a running total of objects constructed and subtract the number of objects destructed. If over the run of your program you find there are excess objects constructed you can narrow the problem down to where objects of that class are newed.

- Related to the previous one if you've got a lost memory block have a look at the first word of the dumped block. If it looks like a pointer it could be the address of the class's vtable - if you have any virtual function. If you're feeling brave you might be able to correlate the address with a class using a map file (/MAP:filename on the linker command line).

- If you want to get the memory layout of a particular class or all classes in a translation unit (handy for looking at your blocks and seeing if you recognise anything in there and finding the vtable ptr) use /d1reportAllClassLayout or /dreportSingleClassLayout<class name=""></class> on the compiler command line

Er, that's about it from me, hope you sort it out soon.
 
Share this answer
 
Comments
Espen Harlinn 31-May-12 15:12pm    
Well answered :-D
[no name] 1-Jun-12 0:04am    
Very good. I have found it useful to set all heap pointers to null when declared and also when freed. So before new is called test the pointer is null. This catches a lot of dangling pointers which can be hard to find and are insidious.
The numbers in curly braces like {657} give you a hint where and when it happens. These are the allocation request numbers. So every single allocation gets a new number and by this number you can track things.

If you can reproduce the memory leak in DEBUG mode and the leaks occur always with the same request numbers you can use the following technique:

- set a breakpoint in dbgheap.c in function _heap_alloc_dbg on the line that says:

lRequest = _lRequestCurr;


Instead of looking for that file in your VC++ installation you can equally well set a breakpoint an arbitrary new statement and drill down with step-into until you arrive at function _heap_alloc_dbg. Then find the above line and set a breakpoint there.

- make this a conditional breakpoint that only triggers for the request number you are looking for

- run your program; hopefully you will land on your breakpoint

- look at the call stack and find out what actually initiated this memory allocation request

It's not a really easy technique, but very helpful in some of the hard cases.
 
Share this answer
 
Comments
Aescleal 31-May-12 8:55am    
This strikes me as one of the courts of last resort when debugging memory allocation problems but a handy one to know when nothing else works.
nv3 31-May-12 9:02am    
Yes, it is kind of a last resort, but has helped me out in a couple of cases. Thanks Ash.
You will have to use some profiling tool to do that. search and you will find some.

Also, check this article. it is also pretty good: Easy Detection of Memory Leaks[^]
 
Share this answer
 
Add the following macro into your source files, after the header includes. When in _DEBUG mode, you'll get the file and line number where the leak was allocated, reported in the output window.

C++
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
 
Share this answer
 
v2
Comments
[no name] 1-Jun-12 0:09am    
Does this work in all cases?
JackDingler 1-Jun-12 8:56am    
If leak is in the module that contains the macro, it does.
A way that I found and use to detect memory leak. You can add following code in header file and overload global new and delete. In debug mode, you can easily identify where the memory leak happens.

struct LogInfo
{
char file[100];
int line;
};

//Create a global map : Key will be memory pointer address and value will be LogInfo object

#ifdef _DEBUG
inline void* operator new (unsigned int size, const char* file, int line)
{
void* ptr = (void*)malloc(size);
//Insert value in map
return ptr;
};

inline void operator delete(void* p)
{
//Remove value from map
free(p);
};
#endif


#ifdef _DEBUG
#define DEBUG_NEW new(__FILE__, __LINE__)
#else
#define DEBUG_NEW new
#endif
#define new DEBUG_NEW


And at the end of your program you can dump your map object to identify where memory leaks has been occured.
 
Share this answer
 
Comments
JackDingler 31-May-12 14:16pm    
Microsoft already provides this capability in their libraries.
Mohibur Rashid 31-May-12 22:37pm    
Wow I have gave that solution in this forum before. and someone deleted my answer, now you are giving the same answer again. let see

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900