Search code examples
memory-leakswxwidgets

Make a Simple wxWidgets Program Without Memory Leaks


I'm trying to make a basic wxWidgets program that doesn't leak any memory (I'm developing on Windows 7 and am using Visual Studio 2010 and trying to use CRT to check for leaks).

I started from the OpenGL sample and gradually worked it down. After adding CRT calls to the OnExit method of my wxApp object (the only place I ever even saw it mentioned), I realized that memory was being leaked everywhere.

I gradually worked it down more until I created this sample code, which makes CRT spit out a huge load of leaks:

#include <wx/glcanvas.h>
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
    #include <wx/wx.h>
#endif

#ifdef __WXMSW__
#include <wx/msw/msvcrt.h>
#endif
#if !defined(_INC_CRTDBG)// || !defined(_CRTDBG_MAP_ALLOC)
    #error "Debug CRT functions have not been included!"
#endif

class App : public wxApp {
    public:
        bool OnInit(void);
        int OnExit(void);
};
bool App::OnInit(void) {
    if (!wxApp::OnInit()) return false;
    return true;
}
int App::OnExit(void) {
    return wxApp::OnExit();
}

int WINAPI WinMain(HINSTANCE h_instance, HINSTANCE h_prev_instance, wxCmdLineArgType cmd_line, int cmd_show) {
    int leaks = _CrtDumpMemoryLeaks();
    if (leaks) {
        int i=0, j=6/i; //Put a breakpoint here or throw an exception
    }

    return EXIT_SUCCESS;
}

#pragma comment(lib,"wxbase29ud.lib")
#pragma comment(lib,"wxmsw29ud_gl.lib")
#pragma comment(lib,"wxmsw29ud_core.lib")
#pragma comment(lib,"wxpngd.lib")
#pragma comment(lib,"wxzlibd.lib")
#pragma comment(lib,"comctl32.lib")
#pragma comment(lib,"rpcrt4.lib")

Notice that the class App is not used anywhere. The function definitions outside the class are necessary to prevent it being optimized away. If the class App is not present, then no errors occur.

The questions are, why isn't this working? How can I make a leak free wxWidgets program? How should I use _CrtDumpMemoryLeaks()? Why aren't there resources about this--and if there are, where are they? The best I could find was this, which only suggested using CRT, but didn't actually say how. Help?


Solution

  • It is possible that are these are not real memory leaks. When you call _CrtDumpMemoryLeaks() it goes through the heap looking for objects that have not been freed and displays them as leaks. Since you are calling it before your application has ended then anything that has been allocated on the heap will show up as leaks.

    I'm pretty sure that wxWidgets creates some global objects (for example, I know there are wxEmptyString, wxDefaultPosition and so forth and I daresay there are others that do actually perform some allocations) that will not be destroyed until after the end of your application. _CrtDumpMemoryLeaks() would need to be called after that point in order to not show false positives.

    You can try to get the CRT to call _CrtDumpMemoryLeaks() automatically on program exit as explained on MSDN.

    There is also a related question here that might help you.

    Edit: I've tried this myself by adding the following code to the top of my App::OnInit() method and the only leaks I get shown are a 64 byte one, which matches my forced leak. So it doesn't look like all wx applications are leaky. However, I also tried it with your code and I do get leaks reported.

    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
    _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR );
    
    int tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
    tmpDbgFlag |= _CRTDBG_LEAK_CHECK_DF;
    _CrtSetDbgFlag(tmpDbgFlag);
    
    // Force a leak
    malloc(64);
    

    Edit 2: You need to include the following line after your App class definition so that wxWidgets uses your App class as the application object (and provides it's own WinMain). I'm guessing that whetever it does in wxApp requires this line in order to clean itself up properly:

    IMPLEMENT_APP(App)
    

    Edit 3: I also found, in the wxWidgets page you linked to that the startup code will automatically call _CrtSetDbgFlag() for you in debug mode. So you get leak detection without having to add the code yourself. You can test this by allocating some memory and not freeing it.