-
Detecting memory leaks (VC8)
When I was using VC6 I could run a program in the debugger and, on closing the program down, VC6's debug output window would flag up a message if the program had leaked any memory. I don't seem to see this any more with VC8. Is there a setting somewhere that I need to enable?
-
Re: Detecting memory leaks (VC8)
I don't know about any option for that, but if exists it is definitely enabled by default. I never had to check anything for that and it works in all the versions I'm using (2005, 2008, 2010). Maybe you just don't have memory leaks. ;)
-
Re: Detecting memory leaks (VC8)
Code:
#include "stdafx.h"
#include <stdio.h>
#include <conio.h>
int _tmain(int argc, _TCHAR* argv[])
{
int *p = new int[20];
printf("Press ENTER to quit");
getchar();
return 0;
}
Hmmm.... am I doing something silly? The above console app should flag up a memory leak in the output window after completion, right?
-
Re: Detecting memory leaks (VC8)
Quote:
Originally Posted by
John E
right?
Nope.
-
Re: Detecting memory leaks (VC8)
The memory leaks were reported when you use the macro DEBUG_NEW in your sources which actually provides a different operator new and operator delete where all allocations and deallocations were watched.
-
Re: Detecting memory leaks (VC8)
Basically, the memory leaks are reported in debug mode when call _CrtDumpMemoryLeaks.
-
Re: Detecting memory leaks (VC8)
-
Re: Detecting memory leaks (VC8)
Quote:
Originally Posted by
Lindley
Interesting.... I've never #included crtdbg.h in my life but this always worked before. Having said that, my old VC6 programs invariably used MFC which I haven't been using since moving to VC8. Maybe that's how crtdbg.h was getting included. Thanks all, for the info.
-
Re: Detecting memory leaks (VC8)
MFC framework and MFC wizards take care of many things which usually we don't even think about... ;)
-
Re: Detecting memory leaks (VC8)
Quote:
Originally Posted by
Lindley
Just found some time to try this and yes, basically it works. According to that article I should see some output looking like this:-
Quote:
Detected memory leaks!
Dumping objects ->
C:\PROGRAM FILES\VISUAL STUDIO\MyProjects\leaktest\leaktest.cpp(20) : {18}
normal block at 0x00780E80, 64 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
and indeed I do see such output as long as I allocated my memory using malloc() - but in my original example (using new) I see this:-
Quote:
Detected memory leaks!
Dumping objects ->
e:\program files\microsoft visual studio 8\vc\include\crtdbg.h(1150) : {90} normal block at 0x00351A60, 80 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
Obviously, that's showing me the location of the debug new operator in crtdbg.h, rather than the position in my source file where new got used. Is there a way to fix this?
-
Re: Detecting memory leaks (VC8)
Just use crtBreakAlloc.
Viggy
-
Re: Detecting memory leaks (VC8)
If you use
Code:
#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
in your 'general header include' and
Code:
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif
in all your ccp-files
In the code I use this I also do
Code:
#if defined(_DEBUG)
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
tmpFlag |= _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF; // Check heap alloc and dump mem leaks at exit
_CrtSetDbgFlag( tmpFlag );
//_crtBreakAlloc = 58652; // in case something very bad happens
assert( !errno );
#endif
as the very first thing in main
-
Re: Detecting memory leaks (VC8)
Thanks guys, I'll try your suggestions later today. MFC has obviously been handling this "under the hood" for many years without me realising the intricacies. The particular project that I'll be building will be using GTK+ though, rather than MFC and I can already see that detecting memory leaks will be considerably more complicated than I thought. Here's a modified version of the simple console app that I used before:-
Code:
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include "stdafx.h"
#include <stdio.h>
#include <conio.h>
#include <string>
#include "..\..\..\+GTK-SOURCES\gnu-mm\libs\glibmm2\glibmm\ustring.h"
const std::string strTest1 = "A test string";
const Glib::ustring strTest2 = "Another test string";
int _tmain(int argc, _TCHAR* argv[])
{
int *p = (int*)malloc(20 * sizeof(int));
printf("Press ENTER to quit");
getchar();
_CrtDumpMemoryLeaks();
return 0;
}
I haven't yet added those new features you guys mentioned but note the global objects strTest1 and strTest2. _CrtDumpMemoryLeaks() flags up a memory leak from strTest2 (a Glib::ustring) presumably because global objects haven't yet released their memory by the time I called _CrtDumpMemoryLeaks().
What's interesting is that no leak got detected from strTest1 (which was a std::string). Things get really interesting though if I build a simple MFC app instead of my console app. In that case, the leak from malloc() gets (correctly) detected but no leaks get detected from either of the global objects.
Clearly MFC is pretty clever about where exactly it calls _CrtDumpMemoryLeaks() and I guess I've a lot more to learn about using this feature properly. Maybe this is a good reason to go back to MFC.... :cool:
No, only joking. This is a cross-platform app, so MFC is out of the question. :cry:
-
Re: Detecting memory leaks (VC8)
We, the MFC fans, were all the years looking for someone who makes MFC a cross-platform library :D
-
Re: Detecting memory leaks (VC8)
Personally I find it rather difficult to determine exactly which gtk+ objects need explicit deletion and which don't, since gtk+ uses some kind of reference counting which isn't documented all that well.
This might be one good reason to choose gtkmm instead; C++ libraries typically do memory stuff a bit more automatically. I don't know gtkmm well enough to say how much they've cleaned things up though.
-
Re: Detecting memory leaks (VC8)
Quote:
Originally Posted by
Lindley
Personally I find it rather difficult to determine exactly which gtk+ objects need explicit deletion and which don't, since gtk+ uses some kind of reference counting which isn't documented all that well.
I have to admit, that is a definite weakness with gtk+. I tend to use gtkmm for new projects.
I haven't had much time to look into this yet so I'm still struggling to figure out how I'll crack the fact that _CrtDumpMemoryLeaks() will be giving me false readings for global objects if I'm not using MFC (it does work fantastically well for an MFC app but not so well in the example I gave).
Is there a way to set a "start point" for leak detection? In other words, to say "ignore any memory allocated before this point because that'll just be the global objects"?
-
Re: Detecting memory leaks (VC8)
I also had some issues when experimenting with _CrtDumpMemoryLeaks() but the method I posted before works alright (VS2010 untested). My guess is that _CrtDumpMemoryLeaks() is called by the debug libs later in the exit (after the globals are destroyed).
If you have dll's in your project you can do the same trick as in main in DllMain DLL_PROCESS_ATTACH but there will be a lot of duplicated reports, most of them without proper file names since the memory holding the information is discarded before the printout.
-
Re: Detecting memory leaks (VC8)
Quote:
Originally Posted by
John E
I have to admit, that is a definite weakness with gtk+. I tend to use gtkmm for new projects.
I haven't had much time to look into this yet so I'm still struggling to figure out how I'll crack the fact that _CrtDumpMemoryLeaks() will be giving me false readings for global objects if I'm not using MFC (it does work fantastically well for an MFC app but not so well in the example I gave).
Is there a way to set a "start point" for leak detection? In other words, to say "ignore any memory allocated before this point because that'll just be the global objects"?
Using the page I linked to earlier, you should be able to set a "memory checkpoint" and then just dump everything that's different between two checkpoints.
-
Re: Detecting memory leaks (VC8)
Thanks guys. Still busy with a different project at the moment but I'll get aorund to trying these asap. :thumb:
-
Re: Detecting memory leaks (VC8)
I tried some further experiments this morning. Here's my app's main loop:-
Code:
int main (int argc, char *argv[])
{
Gtk::Main app(&argc, &argv);
MainWindow mainWnd;
mainWnd.set_title ("Hello World !");
app.run (mainWnd); // <-- This runs my code
_CrtDumpMemoryLeaks();
return 0;
}
As you can see, this app uses libgkt+ (strictly speaking, gtkmm). Note the red line. The red line essentially calls gtk_init() which initialises libgtk+.
If I commented out everything between that red line and my return statement, the resulting code would flag up several hundred memory leaks. I've been in touch with the gtk developers but their attitude is that a 'true' leak is one that gets worse with usage. One-off leaks caused by program initialisations not getting cleaned up are somehow not 'true' leaks. That seems to be the official gtk line. :(
Of course, what I want to find are the leaks in my own code - in other words, anything that leaks during the call to app.run (mainWnd); So I need some way of doing something like this:-
Code:
int main (int argc, char *argv[])
{
Gtk::Main app(&argc, &argv);
MainWindow mainWnd;
mainWnd.set_title ("Hello World !");
_Ignore_Any_Memory_Allocated_So_Far_And_Begin_Leak_Detection_Here();
app.run (mainWnd); // <-- This runs my code
_CrtDumpMemoryLeaks();
return 0;
}
A couple of other web sites suggested a technique similar to S_M_A's (i.e. using _CrtSetDebugFlag) but I can't seem to make it work. No matter where I put my calls to _CrtSetDebugFlag() I always end up with all the memory leaks getting reported. Is there a way to do what I want?
-
Re: Detecting memory leaks (VC8)
Quote:
Originally Posted by
itsmeandnobodyelse
The memory leaks were reported when you use the macro DEBUG_NEW in your sources which actually provides a different operator new and operator delete where all allocations and deallocations were watched.
Noooooo. DEBUG_NEW replaces the normal new and in this case in debug mode the leak report will contain some additional information helping to detect where the leak occurs.
even a regular new will show up on the leak report. DEBUG_NEW does not "make" this happen.
-
Re: Detecting memory leaks (VC8)
I've just been reading about a product called Valgrind. It has a facility for selectively suppressing leak reports from 3rd party modules (e.g. DLLs). i.e. so you can keep track of leaks in your own code whilst ignoring leaks in someone else's code that you can't do anything about. Sadly Valgrind isn't available for Windows. :( Something similar though would be a neat feature for Visual Studio IMHO.
-
Re: Detecting memory leaks (VC8)
John if you follow my suggestion in post #12 and drop the call to _CrtDumpMemoryLeaks() I'm pretty sure you get what you seek. The call is not needed (see post #17).
-
Re: Detecting memory leaks (VC8)
I think I've done it correctly but I still seem to be seeing all the memory leaks. For example if I have no header files and just one source file looking like this:-
Code:
#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif
int main (int argc, char *argv[])
{
char *p = new char[9];
#if defined(_DEBUG)
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
tmpFlag |= _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF; // Check heap alloc and dump mem leaks at exit
_CrtSetDbgFlag( tmpFlag );
//_crtBreakAlloc = 58652; // in case something very bad happens
assert( !errno );
#endif
return 0;
}
I still see the 9 bytes that got allocated before the _CrtSetDbgFlag() stuff. What am I not uncderstanding?
-
Re: Detecting memory leaks (VC8)
Setting the DbgFlags informs the CRT to do a leak check "as late as possible"
it doesn't matter WHEN you've set the LEAK_CHECK flag. At the very start of your program or at the very end makes no difference.
Basically what the crt does for you is (it does a LOT more, but this gives yo a rough idea of what's going on behind the scenes).
Code:
void TheRealMainEntryPoint()
{
initialise_CRT();
call_constructors_of_global_objects();
int ret = main( getargc(), getargv() ); // Call the user provided main()
call_destructors_of_global_objects();
if (debugflag & _CRT_LEAK_CHECK_DF) // Leak report flag set ?
_CrtDumpMemoryLeaks(); // then report leaks.
cleanup_CRT();
ExitProcess(ret);
}
-
Re: Detecting memory leaks (VC8)
Okay, so going back to post #20 (my second code sample) is it possible to achieve what I've been trying to do? I've read a couple of articles suggesting that it should be possible but I haven't been able to make it work so far. :cry:
-
Re: Detecting memory leaks (VC8)
Quote:
Originally Posted by
John E
What's interesting is that no leak got detected from strTest1 (which was a std::string).
This most likely isn't reporting a leak due to the small string optimization that is done with std::string.
Basically, for strings with 15 characters or less, the data for the string is held directly in the string object (and not allocated separately). So there is no memory leak because no memory was allocated.
If you try this with a longer string, you will probably see a leak for the global std::string when calling _CrtDumpMemoryLeaks() at the bottom of main.
-
Re: Detecting memory leaks (VC8)
Quote:
Originally Posted by
John E
I've just been reading about a product called Valgrind. It has a facility for selectively suppressing leak reports from 3rd party modules (e.g. DLLs). i.e. so you can keep track of leaks in your own code whilst ignoring leaks in someone else's code that you can't do anything about. Sadly Valgrind isn't available for Windows. :( Something similar though would be a neat feature for Visual Studio IMHO.
Valgrind is terrific----not just for memory leaks, but for heap corruption errors, and even multithreading errors to a limited degree.
-
Re: Detecting memory leaks (VC8)
John can you post a (minimal) project where you have a problem detecting memory leaks? I just have to try it since, at least in 2005, what I posted worked like a charm.
-
Re: Detecting memory leaks (VC8)
Thanks S_M_A. I've probably confused the issue because my requirement has changed since my original post. At first, I was just trying to enable leak detection. But after I got it working, I hit a different problem....
Just to recap, my app uses libgtk+ whose initialization routines seem to leak memory all over the place - but when I reported it to the gtk+ devs, their attitude was that if a block of memory needs to persist for the full lifetime of the program, failing to release it is somehow not a 'true' memory leak.
The problem is that there are hundreds of such leaks - so finding my own leaks amongst the huge amount of output is extremely difficult. What I want to do is to be able to set up a 'start' point (after I've initialized libgtk+) such that only the leaks after that point will get listed.
To save you from needing to install libgtk+ I've given a similar example in post #24. If you assume that the statement char *p = new char[9]; was in reality my call to gtk_init(), what I'm trying to do is to detect only the leaks which occur after that point.
So if you take this pseudo code as an example:-
Code:
#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif
int main (int argc, char *argv[])
{
char *p1 = new char[9]; // In reality, Gtk::Main() which calls gtk_init() (which introduces all the leaks)
_start_detecting_leaks_here();
char *p2 = new char[15];
return 0;
}
I'd like to have some method of not listing the memory leaked at p1 whilst still listing the memory that got leaked at p2.
It might be worth adding that the gtk code is all external to my app (i.e. all implemented in DLLs). I don't know if that could offer a solution somehow? Let me know if that didn't make sense. :)
-
1 Attachment(s)
Re: Detecting memory leaks (VC8)
I did some quick tests and think that this works pretty alright but do some testing yourself as well. I bet there are more situations that will produce false reports than the one I created.
-
Re: Detecting memory leaks (VC8)
Thanks S_M_A. I was experimenting with your code yesterday and it seems to do exactly what I need. :thumb:
The only bit I didn't understand was this small section:-
Code:
// Uncomment and use callstack to find an allocation without file/line info
//_crtBreakAlloc = 174;
Firstly, I wasn't sure what was the significance of '174'. Secondly, although I did uncomment that line, it didn't seem to make any difference to what I saw in the Output window or the Call Stack window. What should I have been looking for?
John
-
Re: Detecting memory leaks (VC8)
Ah, should have commented that a bit more.
If you uncomment the
Code:
gstringvector.push_back( &gstring );
and run it (after you have and change the var names that I forgot to fixup after adding some underscores...) you will get a report that look something like
Code:
{170} normal block at 0x003CA3A0, 4 bytes long.
Data: < > 00 00 00 00
That leak can't be found by pressing F4 (or double-clicking) since it lacks the file/line info. In these situations the only way to find it is to set _crtBreakAlloc to (in this case) 170 and use the callstack to find where it's allocated. The actual number will vary from situation to situation but not from run to run if you don't change anything else. Setting _crtBreakAlloc will slow down the execution speed though and that may cause things to change but hopefully this type of leaks will be rare.
By the way, I must say that the gtk developers show a very un-professional attitude. Every serious developer should strive for having full control over their code.
Edit: I did some more tests and having containers at file scope produce a lot of false reports without file/line info. Using the _CrtSetDbgFlag method does not do that but instead it reports the dll leaks. :(
-
Re: Detecting memory leaks (VC8)
Quote:
Originally Posted by
S_M_A
By the way, I must say that the gtk developers show a very un-professional attitude.
I must admit that I entirely agree. I tried to persuade them by pointing out the anomalies it creates for gtkmm (the object oriented version of gtk+) - e.g.
Code:
#include <gtkmm.h>
int main (int argc, char *argv[])
{
Gtk::Main *app = new Gtk::Main (&argc, &argv);
delete app;
return 0;
}
The above code literally produces hundreds of memory leaks although I'm sure that most programmers would assume that Gtk::Main::~Main() would have dutifully cleaned them up. In fact I've realised this morning that it's almost impossible to create and delete any kind of gtkmm object without seeing at least half a dozen leaks. Unfortunately, the official view seems to be that you should only release memory arising from the instantiation of an object. One-off allocations needed for its initial setup / registration etc need not be released.
One of my supporters put it very succinctly:- "releasing many thousands of instantiation pointers then failing to release the relatively small number that are left over at the end is a bit like jumping off a sinking ship, swimming all the way to dry land and then letting yourself drown, just before you reach the shore!"
-
Re: Detecting memory leaks (VC8)
I did try to find a way of overcoming the false reports but failed. :(
However thinking about it again I would choose to at least in some of the debug runs use the _CrtSetDbgFlag method. After all, the gtk leaks will be without file/line info so F4 will skip them and just show those in your code.
It's not exactly the perfect streamlined solution but both methods have their pros and cons so what to do...