I want to detect memory leaks of my C++ program in Windows.
I read the documentation also on MSDN about mermoy leak detection and I also started using Visual Leak Detector.
I have a doubt about the reporting of the leaks.
I am expecting a file name with a line number, but I am always reported the text below.
It has all the component of a leak description ( block type, memory address, data, etc..)
except for the file name and the line number.
If it is a real leak?
If yes do you know why the file/line are not reported?
In the meantime I am having a look also at this url
Thanks
Detected memory leaks!
Dumping objects ->
{4723} normal block at 0x04AFB5B8, 8 bytes long.
Data: 2C 3F 00 00 28 3F 00 00
{1476} normal block at 0x04AC3B58, 12 bytes long.
Data: 00 CD CD CD EB 01 75 4C CA 3D 0B 00
Object dump complete.
I investigated quite some different ways of tracking memory leaks. They all have their advantages but also their disadvantages.
To understand their advantages and disadvantages, we have to understand the different mechanisms and requirements:
How are new, delete, malloc and free intercepted? Some tools use #define to redefine new, delete, malloc and free, but this relies on the correct order of the include files, and may give problems if a class contains e.g. a method called free (as is the case in Qt). The preprocessor will also redefine this method, which may lead to compilation errors or unresolved externals.
Another way is to overrule the global new and delete operators. This is a much cleaner solution, but fails is you have a 3rd party library that puts a new in the library, but the delete in the header (or vice versa).
How is the source of the call determined. If new,delete,... are intercepted using #define's, often the preprocessor symbols __FILE__
and __LINE__
are uses to get the source of the leak. However, if you have 'generic' functions in your code like e.g. CreateString(), then most of the leaks will be reported in these generic functions, which does not really help you.
An alternative is to get the call stack at run time. It can be quite easily done using the Windows StackWalk function, but in my experience, this is very very slow. A much faster alternative is to get the base-pointer directly, and to rely on the stack-frame-pointers (you must compile with /Oy- to get the stack-frame-pointers). You can get the frame (base) pointer like this: _asm mov DWORD PTR [FramePtr], ebp
. Then simply loop and in the loop get the instruction pointer from ((ADDR *)FramePtr)[1];
and the next frame-pointer fromFramePtr = ((ADDR *)FramePtr)[0];
How to report the leaks at the exact moment. In my case, I want the leaks to be reported at the end of the application, but to be able to do this, you need a leak-reporting mechanism at the end of your application. This means that if you want to report your leaks yourself, you need to rely on global variables being destructed at the end of your application (and report the leaks in ths destructor of the global variable). For server-type applications, you are probably more interested in getting the difference in memory usage between two points in time.
And now the different leak-systems:
C RunTime: reports leaks at the end, but has no decent way of reporting call stacks. Its method of intercepting calls to new,delete,... may cause problems in combinations with 3rd party libraries (like Qt, Boost, ...)
External Microsoft utilities (like GFlags, UMDH,, ...): they seem to be able to only log differences between two points in time. However, the call stack seems to be much better, although the GFlags utility may set flags in the OS that may cause a serious slowdown of your application.
Visual Leak Detector. Seems to correctly find all leaks, but in my case it doesn't work since I have a 3rd party DLL that simply aborts the process at its DllUnload (seems to be a Windows 7 specific problem).
My personal favorite (and people will not agree with me, I'm sure), is to write your own memory manager. Intercepting can be easily done using global new and delete operators (with the possible problems mentioned above), and you can get the call stack as described above. This alternative also relies on being able to have code that is executed at the very last moment in your application.
When choosing an alternative, I found the following aspects very imporant for my situation:
- I want it to work seemlessly in my application, so that every developer is notified immediately if there is a leak. If you delay leak-checking to a later moment where you use external utilities like Purify, leak-finding will be much harder.
- I want leaks to be reported at the end of the application, automatically.
- I want as much as possible information from the leak (the data, the call stack, ...)
Hope this helps.
This is the output from Visual Studio's own debug CRT, not the output from Visual Leak Detector. Firstly ensure that you're using the current version at Codeplex and that you have #included vld.h in your project. You will get a much more informative output.
I got it after debugging a lot of header files.
Here is what has to be done to enable file/line number in the output
#define _CRTDBG_MAP_ALLOC
#define _CRTDBG_MAP_ALLOC_NEW
Did you compile with debugging information enabled and ensure that the pdb file is available by the leak detector? Without this information it wouldn't be able to provide line numbers.
You should use Valgrind, it's very powerfull and explains properly where are the leaks located in your program. Your program may need to be compiled with gcc, though...
Rational Purify is available as a for-money plugin for VC++, and is a very good leak (and other trouble) detector. I used to use it a lot on Solaris, and it was very easy to use and clear. I've also heard good things from other people about the version for use with Visual Studio, but I've never actually tried that.
FWIW, I suspect that Purify was the inspiration for Valgrind, which has already been mentioned.
If the allocation numbers (the ones in the curled braces) are always the same, this could help. Basically, it described how to make VC++ generate a breakpoint when the allocation with the specified number is attempted.