[wxMSW, MSVC7] how to spot memory leaks
Noel Diviney
divner at hotmail.com
Mon Feb 5 13:21:11 PST 2007
Hi Francesco,
The following is my response to a question from Klaas some time back.
It also works with VS 2003.net.
I have not looked at wxPlot recently but you will get the drift.
By the way there used to be a lot of helpful stuff on the old wxWidgets site
on things like this (part of the Community stuff and maintained I think by Arnout)
which now appears to have go west. Any clues? There used to be something
on wxActiveX abd viewing PDFs from within one's application which I have an
interest in at the moment.
Hope this helps and best regards,
Noel.
k. holwerda wrote:
Hi,
I am trying to find why my VC6 does not add line number and file afterby leaks.
The operator new in object.cpp down here is called, but the filename isempty and lineNum is 0.
In my setup.h i made:
#define wxUSE_DEBUG_CONTEXT 1
#define wxUSE_MEMORY_TRACING 1
because if i don't i also do not get the file and linenumbers.
I know this disables wxUSE_VC_CRTDBG, but i don't, i also do not getlinenumbers in the report of leaks.
Is there something to be set in VC6 to make those linenumbers appear?
How do you people do leak debugging? I need at least linenumber and filewhere the leak took place.
Thanks for some help,
Klaas
void *wxObject::operator new ( size_t size, const wxChar *fileName, intlineNum )
{
return wxDebugAlloc(size, (wxChar*) fileName, lineNum, true);
}
Hi Klass,
I use VC++ 6.00 and this what I do.
I don't change anything in setup.h.
After all the other #includes in your source files add
#ifdef __WXMSW__
#include
#endif
Take a look at msvcrt.h. Everything is set up there to add
the Filename and Line Numbers compliments of Julian and Vadim.
The following is some work I have done on the Plot sample in
contrib which leaks like a sieve. I have to learn Bakefiles
and how to submit a patch to take it further.
Best regards,
Noel Diviney.
HOWTO ... Building the Plot Library and testing for Memory Leaks.
First of all the plot.dsw and plot.dsp in contrib\samples\plot
are wrong and do not allow the project to be loaded properly.
In the contrib\samples\plot directory rename the following files
plot.dsw to plottest.dsw
plot.dsp to plottest.dsp
plot.cpp to plottest.cpp
plot.rc to plottest.rc
Edit the following lines in plottest.dsw
Project: "plot"=plot.dsp - Package Owner=
to
Project: "plottest"=plottest.dsp - Package Owner=
Project: "plot"=..\..\..\build\msw\wx_plot.dsp - Package Owner=
to
Project: "plot"=..\..\build\plot\plot.dsp - Package Owner=
In plottest.dsp edit all instances of plot to be plottest
Tick the "Whole Word" control so as not to change the library names
ie wxmswuniv26u_plot.lib.
Plottest.dsw should now load and build.
//--------------------------------------------------------------------------
The sample plottest.exe should now execute but it has memory leaks.
To test for the memory leaks start plottest.exe in debug mode as follows
Build->Start Debug->Go
Now close the plottest.exe application and you should see the following
in the output window
Detected memory leaks!
Dumping objects ->
{2453} normal block at 0x00B52ED0, 12 bytes long.
Data: < > E8 03 00 00 D0 07 00 00 00 00 00 00
{2452} normal block at 0x00B52E88, 12 bytes long.
Data: 64 00 00 00 90 01 00 00 00 00 00 00
{2451} normal block at 0x00B52E40, 12 bytes long.
Data: < > 19 00 00 00 1E 00 00 00 00 00 00 00
{2450} normal block at 0x00B52DB8, 64 bytes long.
Data: 70 2D B5 00 40 2E B5 00 88 2E B5 00 D0 2E B5 00
{2449} normal block at 0x00B52D70, 12 bytes long.
Data: < > 0A 00 00 00 14 00 00 00 00 00 00 00
{2448} normal block at 0x00B52D08, 32 bytes long.
Data: 7C F2 5C 00 00 00 00 00 0A 00 00 00 0A 00 00 00
{2446} normal block at 0x00B52C38, 56 bytes long.
Data: 74 F1 5C 00 00 00 00 00 32 00 00 00 CD CD CD CD
{2444} normal block at 0x00B52A30, 56 bytes long.
Data: 74 F1 5C 00 00 00 00 00 00 00 00 00 CD CD CD CD
{2330} normal block at 0x00B50680, 12 bytes long.
Data: < ] > E4 B1 5D 00 00 00 00 00 90 0D 05 AF
{2329} normal block at 0x00B50608, 52 bytes long.
Data: 7C B1 5D 00 01 00 00 00 14 00 00 00 12 00 00 00
{2327} normal block at 0x00B50558, 12 bytes long.
Data: 34 05 5D 00 08 06 B5 00 00 CD CD CD
{2316} normal block at 0x00B500E8, 12 bytes long.
Data: < ] g > E4 B1 5D 00 00 00 00 00 67 09 05 A7
{2315} normal block at 0x00B50070, 52 bytes long.
Data: 7C B1 5D 00 01 00 00 00 14 00 00 00 12 00 00 00
{2313} normal block at 0x00B4FFC0, 12 bytes long.
Data: 34 05 5D 00 70 00 B5 00 00 CD CD CD
{2300} normal block at 0x00B4FA80, 12 bytes long.
Data: < ] T > E4 B1 5D 00 00 00 00 00 54 0E 05 F6
{2299} normal block at 0x00B4FA08, 52 bytes long.
Data: 7C B1 5D 00 01 00 00 00 14 00 00 00 12 00 00 00
{2297} normal block at 0x00B4F958, 12 bytes long.
Data: 34 05 5D 00 08 FA B4 00 00 CD CD CD
{2286} normal block at 0x00B4F4E8, 12 bytes long.
Data: < ] u > E4 B1 5D 00 00 00 00 00 75 0E 05 EF
{2285} normal block at 0x00B4F470, 52 bytes long.
Data: 7C B1 5D 00 01 00 00 00 14 00 00 00 12 00 00 00
{2283} normal block at 0x00B4F3C0, 12 bytes long.
Data: 34 05 5D 00 70 F4 B4 00 00 CD CD CD
{2269} normal block at 0x00B4EE28, 12 bytes long.
Data: < ] q> E4 B1 5D 00 00 00 00 00 9A 0E 05 71
{2268} normal block at 0x00B4EDB0, 52 bytes long.
Data: 7C B1 5D 00 01 00 00 00 14 00 00 00 14 00 00 00
{2266} normal block at 0x00B4ED00, 12 bytes long.
Data: 34 05 5D 00 B0 ED B4 00 00 CD CD CD
{2240} normal block at 0x00B4E470, 12 bytes long.
Data: < ] > E4 B1 5D 00 00 00 00 00 CC 0D 05 0D
{2239} normal block at 0x00B4E3F8, 52 bytes long.
Data: 7C B1 5D 00 01 00 00 00 14 00 00 00 14 00 00 00
{2237} normal block at 0x00B4CEF8, 12 bytes long.
Data: 34 05 5D 00 F8 E3 B4 00 00 CD CD CD
Object dump complete.
This is great news but you have no idea where these leaks are being
created. To find out proceed as follows.
//--------------------------------------------------------------------------
Thanks to Julian and Vadim it is easy to get VC++ 6.00 to tell us.
in both of the source files plot.cpp and plottest.cpp edit as follows
After all the other #includes add
#ifdef __WXMSW__
#include
#endif
This will have src filename and line numbers added to the leaks
Recompile in debug mode and execute as above.
The dump now looks like this
Dumping objects ->
E:\wxWidgets-2.6.1\contrib\src\plot\plot.cpp(151) : {2454}
normal block at 0x00B52F28, 12 bytes long.
Data: < > E8 03 00 00 D0 07 00 00 00 00 00 00
E:\wxWidgets-2.6.1\contrib\src\plot\plot.cpp(151) : {2453}
normal block at 0x00B52EE0, 12 bytes long.
Data: 64 00 00 00 90 01 00 00 00 00 00 00
E:\wxWidgets-2.6.1\contrib\src\plot\plot.cpp(151) : {2452}
normal block at 0x00B52E98, 12 bytes long.
Data: < > 19 00 00 00 1E 00 00 00 00 00 00 00
{2451} normal block at 0x00B52E10, 64 bytes long.
Data: < - . . (/ > C8 2D B5 00 98 2E B5 00 E0 2E B5 00 28 2F B5 00
E:\wxWidgets-2.6.1\contrib\src\plot\plot.cpp(151) : {2450}
normal block at 0x00B52DC8, 12 bytes long.
Data: < > 0A 00 00 00 14 00 00 00 00 00 00 00
E:\wxWidgets-2.6.1\contrib\samples\plot\plottest.cpp(139) : {2449}
normal block at 0x00B52D60, 32 bytes long.
Data: 7C 02 5D 00 00 00 00 00 0A 00 00 00 0A 00 00 00
E:\wxWidgets-2.6.1\contrib\samples\plot\plottest.cpp(138) : {2447}
normal block at 0x00B52C90, 56 bytes long.
Data: 74 01 5D 00 00 00 00 00 32 00 00 00 CD CD CD CD
E:\wxWidgets-2.6.1\contrib\samples\plot\plottest.cpp(137) : {2445}
normal block at 0x00B52A88, 56 bytes long.
Data: 74 01 5D 00 00 00 00 00 00 00 00 00 CD CD CD CD
{2330} normal block at 0x00B50680, 12 bytes long.
Data: < ] f> E4 C1 5D 00 00 00 00 00 CA 0B 05 66
{2329} normal block at 0x00B50608, 52 bytes long.
Data: 7C C1 5D 00 01 00 00 00 14 00 00 00 12 00 00 00
E:\wxWidgets-2.6.1\contrib\src\plot\plot.cpp(1114) : {2327}
normal block at 0x00B50558, 12 bytes long.
Data: 34 15 5D 00 08 06 B5 00 00 CD CD CD
{2317} normal block at 0x00B50140, 12 bytes long.
Data: < ] E> E4 C1 5D 00 00 00 00 00 CD 0B 05 45
{2316} normal block at 0x00B500C8, 52 bytes long.
Data: 7C C1 5D 00 01 00 00 00 14 00 00 00 12 00 00 00
E:\wxWidgets-2.6.1\contrib\src\plot\plot.cpp(1095) : {2314}
normal block at 0x00B50018, 12 bytes long.
Data: 34 15 5D 00 C8 00 B5 00 00 CD CD CD
{2300} normal block at 0x00B4FA80, 12 bytes long.
Data: < ] 4> E4 C1 5D 00 00 00 00 00 CE 0B 05 34
{2299} normal block at 0x00B4FA08, 52 bytes long.
Data: 7C C1 5D 00 01 00 00 00 14 00 00 00 12 00 00 00
E:\wxWidgets-2.6.1\contrib\src\plot\plot.cpp(1152) : {2297}
normal block at 0x00B4F958, 12 bytes long.
Data: 34 15 5D 00 08 FA B4 00 00 CD CD CD
{2286} normal block at 0x00B4F4E8, 12 bytes long.
Data: < ] > E4 C1 5D 00 00 00 00 00 C0 0B 05 15
{2285} normal block at 0x00B4F470, 52 bytes long.
Data: 7C C1 5D 00 01 00 00 00 14 00 00 00 12 00 00 00
E:\wxWidgets-2.6.1\contrib\src\plot\plot.cpp(1133) : {2283}
normal block at 0x00B4F3C0, 12 bytes long.
Data: 34 15 5D 00 70 F4 B4 00 00 CD CD CD
{2269} normal block at 0x00B4EE28, 12 bytes long.
Data: < ] /> E4 C1 5D 00 00 00 00 00 D4 0B 05 2F
{2268} normal block at 0x00B4EDB0, 52 bytes long.
Data: 7C C1 5D 00 01 00 00 00 14 00 00 00 14 00 00 00
E:\wxWidgets-2.6.1\contrib\src\plot\plot.cpp(1076) : {2266}
normal block at 0x00B4ED00, 12 bytes long.
Data: 34 15 5D 00 B0 ED B4 00 00 CD CD CD
{2240} normal block at 0x00B4E470, 12 bytes long.
Data: < ] [> E4 C1 5D 00 00 00 00 00 E2 0B 05 5B
{2239} normal block at 0x00B4E3F8, 52 bytes long.
Data: 7C C1 5D 00 01 00 00 00 14 00 00 00 14 00 00 00
E:\wxWidgets-2.6.1\contrib\src\plot\plot.cpp(1057) : {2237}
normal block at 0x00B4CEF8, 12 bytes long.
Data: 34 15 5D 00 F8 E3 B4 00 00 CD CD CD
Object dump complete.
Now we have something to work with.
//--------------------------------------------------------------------------
Lets start with plot.cpp line 151.
These are due to the PlotOnOffCurve lines and are added to m_marks which is
an wxArray. To fix we need to add a destructor to PlotOnOffCurve as follows
in Plot.h add
~wxPlotOnOffCurve();
In plot.cpp add
wxPlotOnOffCurve::~wxPlotOnOffCurve()
{
m_marks.Clear();
}
//--------------------------------------------------------------------------
Next we have plottest.cpp line 137 138 and 139
These are due to the PlotCurve objects. My solution is to add
some ptr variables to the PlotWindow class
wxPlotCurve*m_curve_1;
wxPlotCurve*m_curve_2;
wxPlotOnOffCurve*m_curve_3;
We can now use these variables in the PlotWindow class implementation as follows
m_curve_1 = new MyPlotCurve( 0, -1.5, 1.5 );
m_plot->Add(m_curve_1);
m_curve_2 = new MyPlotCurve( 50, -1.5, 1.5 );
m_plot->Add(m_curve_2);
m_curve_3 = new wxPlotOnOffCurve( 10 );
m_curve_3->Add( 10, 20 );
m_curve_3->Add( 25, 30 );
m_curve_3->Add( 100, 400 );
m_curve_3->Add( 1000, 2000 );
m_plot->Add(m_curve_3);
and then manually delete them on closing by adding a descructor to MyFrame
MyFrame::~MyFrame()
{
delete m_curve_1;
delete m_curve_2;
delete m_curve_3;
}
You need to add the destructor also to MyFrame class declaration in Plot.h
~MyFrame();
//--------------------------------------------------------------------------
Finally we have six leaks in plot.cpp at lines 1114, 1095, 1152, 1133, 1076
and 1057. These are to do with the button controls on the left of the
Plot Window. To fix these we again require 6 pointer variables to hold
the pointers and then manually delete them at the end
Add the following to Plot.h class wxPlotWindow private:
wxBitmap *m_dwnBitmap;
wxBitmap *m_upBitmap;
wxBitmap *m_enlBitmap;
wxBitmap *m_shrBitmap;
wxBitmap *m_zinBitmap;
wxBitmap *m_zopBitmap;
Then use these pointers to create the buttons in plot.cpp wxPlotWindow
constructor as follows
if ((GetWindowStyleFlag() & wxPLOT_BUTTON_ENLARGE) != 0)
{
m_enlBitmap = GetEnlargeBitmap();
m_shrBitmap = GetShrinkBitmap();
buttonlist->Add( new wxBitmapButton( this, ID_ENLARGE,
*m_enlBitmap ), 0, wxEXPAND|wxALL, 2 );
buttonlist->Add( new wxBitmapButton( this, ID_SHRINK,
*m_shrBitmap ), 0, wxEXPAND|wxALL, 2 );
buttonlist->Add( 20,10, 0 );
}
if ((GetWindowStyleFlag() & wxPLOT_BUTTON_MOVE) != 0)
{
m_dwnBitmap = GetDownBitmap();
m_upBitmap = GetUpBitmap();
buttonlist->Add( new wxBitmapButton( this, ID_MOVE_UP,
*m_upBitmap ), 0, wxEXPAND|wxALL, 2 );
buttonlist->Add( new wxBitmapButton( this, ID_MOVE_DOWN,
*m_dwnBitmap ), 0, wxEXPAND|wxALL, 2 );
buttonlist->Add( 20,10, 0 );
}
if ((GetWindowStyleFlag() & wxPLOT_BUTTON_ZOOM) != 0)
{
m_zinBitmap = GetZoomInBitmap();
m_zopBitmap = GetZoomOutBitmap();
buttonlist->Add( new wxBitmapButton( this, ID_ZOOM_IN,
*m_zinBitmap ), 0, wxEXPAND|wxALL, 2 );
buttonlist->Add( new wxBitmapButton( this, ID_ZOOM_OUT,
*m_zopBitmap ), 0, wxEXPAND|wxALL, 2 );
}
mainsizer->Add( buttonlist, 0, wxEXPAND|wxALL, 4 );
The destructor to delete the memory is added to wxPlotWindow in plot.cpp
as follows
wxPlotWindow::~wxPlotWindow()
{
if (m_enlBitmap)
delete m_enlBitmap;
if (m_shrBitmap)
delete m_shrBitmap;
if (m_dwnBitmap)
delete m_dwnBitmap;
if (m_upBitmap)
delete m_upBitmap;
if (m_zinBitmap)
delete m_zinBitmap;
if (m_zopBitmap)
delete m_zopBitmap;
}
Add a destructor declaration to plot.h as well
~wxPlotWindow();
As these buttons are conditional it is a good idea to
initialise them to NULL in the constructor
m_enlBitmap = NULL;
m_shrBitmap = NULL:
m_dwnBitmap = NULL;
m_upBitmap = NULL;
m_zinBitmap = NULL;
m_zopBitmap = NULL;
Well thats all there is to it.
There should be no memory leaks evident now.
Noel Diviney Ayrenet Pty Ltd,5 Cochrane St.,Mitcham, Vic. 3132, Australia Phone +61 3 9873 7300 email divner at hotmail.com
_________________________________________________________________
Get the new Windows Live Messenger!
http://get.live.com/messenger/overview
More information about the wx-users
mailing list