This article is a hint for those who feel desperate with finding the origin of a memory leak in their programs. I suppose you've already read the Microsoft's documentation on this topic - Finding Memory Leaks Using the CRT Library - and set up your project to enable leak detection.
The documentation states that if you did everything properly, the Output window should display all the leaked memory blocks along with source file names and line numbers. However sometimes it's not the case and there's nothing shown except a bare memory address and allocation size. And you end up staring at these numbers, puzzling over what you could do wrong with leak detection setup, placing exit()s all over the code and trying to understand logically where those damned leaks could originate from.
Actually this might be not your fault that you don't see line numbers. To be precise, it's not your fault but it's a problem of your project's design. Probably your project uses many global variables which get initialized long before source line number tracking is in effect and thus in the end debug CRT detects leaks but cannot report line numbers. Global variable usage is unavoidable in large and complex projects so we need some method to fix such leaks.
The good news is that such method exists. The bad news is that it involves much manual work. But at least it works.
It is crucial to run your program every time with the same input conditions so as to memory allocation numbers stay unchanged between runs. Once you fixed a leak, you'll need to repeat the whole process from the start as allocation numbers likely have changed.
Hope this info will help fixing your very own leaks.
Actually this might be not your fault that you don't see line numbers. To be precise, it's not your fault but it's a problem of your project's design. Probably your project uses many global variables which get initialized long before source line number tracking is in effect and thus in the end debug CRT detects leaks but cannot report line numbers. Global variable usage is unavoidable in large and complex projects so we need some method to fix such leaks.
The good news is that such method exists. The bad news is that it involves much manual work. But at least it works.
- First you'll need to make a whole program run to get the entire memory leak report in the Output window. Copy the memory leak report somewhere, e.g. to a Notepad window, as later you'll need these numbers in curly braces called memory allocation numbers.
- Open the crt0dat.c file in Visual Studio. I assume that during the Visual C++ installation you had chosen the default folder, so that file should be located in "C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src".
- Within the crt0dat.c file, search for the following string (no quotes): "__cdecl _initterm_e". Place a breakpoint at the first statement of the _initterm_e() function.
- Run your program again. The execution stops at your breakpoint. Now go to the Watch window and type "_crtBreakAlloc" (no quotes) in the Name column. In the Value column most probably you'll see -1.
- Disable the breakpoint in crt0dat.c. You won't need it to be hit again during this program run.
- Now get back to your Notepad window and copy to the clipboard the first of the memory allocation numbers in curly braces. Go to the Watch window in Visual Studio and in the Value column replace the value shown with the value in the clipboard. Press Enter.
- Resume the execution by hitting F5 or choosing Continue from the menu. After a while Visual Studio should display a message that reads "<YourProgram> has triggered a breakpoint" and stops at some location within the CRT debug code, most likely in the dbgheap.c file.
- Now go to the Call Stack window and scan it from the top to the bottom until you find a function that is known to be written by you. Now you can conclude on what can be the reason of the memory leak. It might turn so that at the top or in the middle of the call stack there are gray lines containing only addresses. This means that symbol information is absent for some libraries used in your project. Hit Shift-F11 until you get rid of gray lines before the known functions. Ignore "No source code available" messages if they appear and keep hitting Shift-F11.
- Once you finished your investigation with one of the leaks, you may continue with another without restarting the program. Just get the next memory allocation number from the previous memory leak report, paste it into the Value column for _crtBreakAlloc in the Watch window and hit F5. Investigate the cause of the leak. Repeat these steps until you examine all leaks you have. This works thanks to that memory leaks reported in the same order as the corresponding memory allocations happen.
It is crucial to run your program every time with the same input conditions so as to memory allocation numbers stay unchanged between runs. Once you fixed a leak, you'll need to repeat the whole process from the start as allocation numbers likely have changed.
Hope this info will help fixing your very own leaks.