Detecting Memory Leaks and Other Errors

team bbl


Ideally, when your application exits, all objects will be cleaned up either by your application or by wxWidgets itself, and no allocated memory will be left for the operating system to clean up automatically. Although it may be tempting simply not to bother with some cleanup, you really should take care to clean everything up yourself. Often such memory leaks are symptomatic of a problem with your code that could lead to large amounts of memory being wasted during a session. It's much harder to go back and figure out where leaks are coming from after you have moved on to another aspect of your application, so try to have zero tolerance for leaks.

So how do you know whether your application is leaking memory? Various third-party memory-checking tools are available to do this and more, and wxWidgets has a simple built-in memory checker. To use this checker for your debug configuration, you need to set some switches in setup.h (Windows) or configure (other platforms or GCC on Windows).

On Windows, these are:

 #define wxUSE_DEBUG_CONTEXT 1 #define wxUSE_MEMORY_TRACING 1 #define wxUSE_GLOBAL_MEMORY_OPERATORS 1 #define wxUSE_DEBUG_NEW_ALWAYS 1 

For configure, pass these switches:

 --enable-debug --enable-mem_tracing --enable-debug_cntxt 

There are some restrictions to this system: it doesn't work for MinGW or Cygwin (at the time of writing), and you cannot use wxUSE_DEBUG_NEW_ALWAYS if you are using STL in your application or the CodeWarrior compiler.

If wxUSE_DEBUG_NEW_ALWAYS is on, then all instances of the new operator in wxWidgets and your code will be defined to be new(__TFILE__,__LINE__), which has been reimplemented to use custom memory allocation and deletion routines. To use this version of new explicitly, without defining new, use WXDEBUG_NEW where you would normally write new.

The easiest way to use the memory checking system is to do nothing special at all: just run your application in the debugger, quit the application, and see if any memory leaks are reported. Here's an example of a report:

 There were memory leaks. - Memory dump - .\memcheck.cpp(89): wxBrush at 0xBE44B8, size 12 ..\..\src\msw\brush.cpp(233): non-object data at 0xBE55A8, size 44 .\memcheck.cpp(90): wxBitmap at 0xBE5088, size 12 ..\..\src\msw\bitmap.cpp(524): non-object data at 0xBE6FB8, size 52 .\memcheck.cpp(93): non-object data at 0xBB8410, size 1000 .\memcheck.cpp(95): non-object data at 0xBE6F58, size 4 .\memcheck.cpp(98): non-object data at 0xBE6EF8, size 8 - Memory statistics - 1 objects of class wxBitmap, total size 12 5 objects of class nonobject, total size 1108 1 objects of class wxBrush, total size 12 Number of object items: 2 Number of non-object items: 5 Total allocated size: 1132 

This example tells us that a wxBrush and a wxBitmap were allocated but not freed, along with some other objects whose class is unknown because they do not have wxWidgets type information. In some IDEs, you can double-click on the line with the error and see the source line at which the object was allocated. This functionality is a very good first step in tracking down the cause of the memory leak. For best results, add run-time type information (RTTI) to any classes that are descendants of wxObject. Add DECLARE_CLASS(class) in your class declaration and IMPLEMENT_CLASS(class, parentClass) somewhere in your implementation file.

The memory checking system also tries to catch memory overwrite and double-deletion bugs. The allocation routines write a special signature for a "good" block of memory and another signature for deleted memory. If the application tries to delete a block without the signature, the problem will be reported, as will a deletion that occurs when the block has already been deleted. This will make it easier to catch the kind of memory bugs that only cause problems some time after the real error has occurred.

Using static members of the wxDebugContext class, you can get a listing of the current objects in the system with PrintClasses or show a count of objects and non-objects (those without wxWidgets RTTI information) with PrintStatistics. Using SetCheckpoint, you can tell wxDebugContext to only show statistics from the checkpoint onwards, ignoring memory allocations done prior to this point. For more details, see samples/memcheck and the reference for wxDebugContext.

Instead of using the basic system in wxWidgets, you may want to use a commercial tool such as BoundsChecker, Purify, or AQtime, or a free alternative such as StackWalker, ValGrind, Electric Fence, or MMGR from Fluid Studios. If you are using Visual C++, wxWidgets uses the compiler's standard leak detection, which doesn't report class names but gives you the line numbers. For best results, make sure wxUSE_DEBUG_NEW_ALWAYS is set to 1 in setup.h. Because it redefines new, you might need to disable it if it causes problems with other libraries.

    team bbl



    Cross-Platform GUI Programming with wxWidgets
    Cross-Platform GUI Programming with wxWidgets
    ISBN: 0131473816
    EAN: 2147483647
    Year: 2005
    Pages: 262

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net