wxGTK: Invalid free() call Topic is solved

Do you have a typical platform dependent issue you're battling with ? Ask it here. Make sure you mention your platform, compiler, and wxWidgets version.
Post Reply
vid512
Experienced Solver
Experienced Solver
Posts: 55
Joined: Mon Feb 08, 2010 10:16 am

wxGTK: Invalid free() call

Post by vid512 »

Following code causes "double free() or corruption" glibc error on wxGTK. Happens with both 2.8.11 and 2.9.1. Same code works fine on wxMSW.

Code: Select all

#include <wx/wx.h>

class MyApp: public wxApp
{
    virtual bool OnInit();
};

IMPLEMENT_APP(MyApp)

class MyDlg: public wxDialog
{
protected:
	void OnOK(wxCommandEvent& event);
	void OnCancel(wxCommandEvent& event);
public:
	MyDlg();
	bool Show();
	DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(MyDlg, wxDialog)
	EVT_BUTTON(wxID_CANCEL, MyDlg::OnCancel)
	EVT_BUTTON(wxID_OK, MyDlg::OnOK)
END_EVENT_TABLE()

MyDlg::MyDlg()
:wxDialog(0, -1, wxT("Dialog"), wxDefaultPosition, wxSize(200, 100))
{
	new wxStaticText(this, -1, wxT("Text"), wxPoint(0, 0));
	new wxButton(this, wxID_OK, wxT("&OK"), wxPoint(0, 30), wxSize(40, 30));
	SetEscapeId(wxID_CANCEL);
	SetFocus();
}

bool MyDlg::Show()
{
	return (bool)ShowModal();
}

void MyDlg::OnOK(wxCommandEvent& event)
{
	Destroy();
	SetReturnCode(1);
}

void MyDlg::OnCancel(wxCommandEvent& event)
{
	Destroy();
	SetReturnCode(0);
}

bool MyApp::OnInit()
{
	MyDlg dlg;
	if (dlg.Show())
		wxMessageBox(wxT("true"));
	else
		wxMessageBox(wxT("false"));
}
Full glib error info:

Code: Select all

*** glibc detected *** ./test: double free or corruption (out): 0xbffb8d40 ***
======= Backtrace: =========
/lib/libc.so.6(+0x6c501)[0x3b9501]
/lib/libc.so.6(+0x6dd70)[0x3bad70]
/lib/libc.so.6(cfree+0x6d)[0x3bde5d]
/usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0x1ba441]
./test[0x80514a0]
/usr/local/lib/libwx_gtk2u-2.9.so.1(_ZN16wxAppConsoleBase20DeletePendingObjectsEv+0x98)[0xfe8a6e]
/usr/local/lib/libwx_gtk2u-2.9.so.1(_ZN16wxAppConsoleBase20ProcessPendingEventsEv+0x1a6)[0xfe8834]
/usr/local/lib/libwx_gtk2u-2.9.so.1(_ZN5wxApp6DoIdleEv+0xb1)[0x113f765]
/usr/local/lib/libwx_gtk2u-2.9.so.1(+0x3916aa)[0x113f6aa]
/lib/libglib-2.0.so.0(+0x3b841)[0x613841]
/lib/libglib-2.0.so.0(g_main_context_dispatch+0x1d5)[0x615855]
/lib/libglib-2.0.so.0(+0x41668)[0x619668]
/lib/libglib-2.0.so.0(g_main_loop_run+0x187)[0x619ba7]
/usr/lib/libgtk-x11-2.0.so.0(gtk_main+0xb9)[0x30d31d9]
/usr/local/lib/libwx_gtk2u-2.9.so.1(_ZN14wxGUIEventLoop3RunEv+0x84)[0x1160638]
/usr/local/lib/libwx_gtk2u-2.9.so.1(_ZN8wxDialog9ShowModalEv+0x196)[0x11be93c]
./test[0x804fafa]
./test[0x804fb85]
./test[0x805079a]
/usr/local/lib/libwx_gtk2u-2.9.so.1(_Z7wxEntryRiPPw+0x78)[0x1058471]
/usr/local/lib/libwx_gtk2u-2.9.so.1(_Z7wxEntryRiPPc+0x3e)[0x1058567]
./test[0x804f3af]
/lib/libc.so.6(__libc_start_main+0xe7)[0x363ce7]
./test[0x804f301]
======= Memory map: ========
00110000-001ef000 r-xp 00000000 08:02 1589472    /usr/lib/libstdc++.so.6.0.14
001ef000-001f3000 r--p 000de000 08:02 1589472    /usr/lib/libstdc++.so.6.0.14
001f3000-001f4000 rw-p 000e2000 08:02 1589472    /usr/lib/libstdc++.so.6.0.14
001f4000-001fb000 rw-p 00000000 00:00 0 
001fb000-0028f000 r-xp 00000000 08:02 1597716    /usr/lib/libgdk-x11-2.0.so.0.2200.0
0028f000-00291000 r--p 00094000 08:02 1597716    /usr/lib/libgdk-x11-2.0.so.0.2200.0
00291000-00292000 rw-p 00096000 08:02 1597716    /usr/lib/libgdk-x11-2.0.so.0.2200.0
00293000-002ab000 r-xp 00000000 08:02 1590158    /usr/lib/libatk-1.0.so.0.3209.1
002ab000-002ac000 ---p 00018000 08:02 1590158    /usr/lib/libatk-1.0.so.0.3209.1
002ac000-002ad000 r--p 00018000 08:02 1590158    /usr/lib/libatk-1.0.so.0.3209.1
002ad000-002ae000 rw-p 00019000 08:02 1590158    /usr/lib/libatk-1.0.so.0.3209.1
002ae000-002d2000 r-xp 00000000 08:02 1593425    /usr/lib/libpangoft2-1.0.so.0.2800.2
002d2000-002d3000 r--p 00023000 08:02 1593425    /usr/lib/libpangoft2-1.0.so.0.2800.2
002d3000-002d4000 rw-p 00024000 08:02 1593425    /usr/lib/libpangoft2-1.0.so.0.2800.2
002d4000-002eb000 r-xp 00000000 08:02 1597755    /usr/lib/libgdk_pixbuf-2.0.so.0.2200.0
002eb000-002ec000 r--p 00017000 08:02 1597755    /usr/lib/libgdk_pixbuf-2.0.so.0.2200.0
002ec000-002ed000 rw-p 00018000 08:02 1597755    /usr/lib/libgdk_pixbuf-2.0.so.0.2200.0
002ed000-00310000 r-xp 00000000 08:02 1916988    /lib/libpng12.so.0.44.0
00310000-00311000 r--p 00022000 08:02 1916988    /lib/libpng12.so.0.44.0
00311000-00312000 rw-p 00023000 08:02 1916988    /lib/libpng12.so.0.44.0
00312000-00314000 r-xp 00000000 08:02 1590951    /usr/lib/libgmodule-2.0.so.0.2600.1
00314000-00315000 r--p 00002000 08:02 1590951    /usr/lib/libgmodule-2.0.so.0.2600.1
00315000-00316000 rw-p 00003000 08:02 1590951    /usr/lib/libgmodule-2.0.so.0.2600.1
00316000-00335000 r-xp 00000000 08:02 1594372    /usr/lib/libjpeg.so.62.0.0
00335000-00336000 r--p 0001e000 08:02 1594372    /usr/lib/libjpeg.so.62.0.0
00336000-00337000 rw-p 0001f000 08:02 1594372    /usr/lib/libjpeg.so.62.0.0
00337000-00345000 r-xp 00000000 08:02 1594359    /usr/lib/libXext.so.6.4.0
00345000-00346000 r--p 0000d000 08:02 1594359    /usr/lib/libXext.so.6.4.0
00346000-00347000 rw-p 0000e000 08:02 1594359    /usr/lib/libXext.so.6.4.0
00347000-00349000 r-xp 00000000 08:02 1590305    /usr/lib/libXinerama.so.1.0.0
00349000-0034a000 r--p 00001000 08:02 1590305    /usr/lib/libXinerama.so.1.0.0
0034a000-0034b000 rw-p 00002000 08:02 1590305    /usr/lib/libXinerama.so.1.0.0
0034c000-0034d000 r-xp 00000000 00:00 0          [vdso]
0034d000-004a4000 r-xp 00000000 08:02 1919295    /lib/libc-2.12.1.so
004a4000-004a6000 r--p 00157000 08:02 1919295    /lib/libc-2.12.1.so
004a6000-004a7000 rw-p 00159000 08:02 1919295    /lib/libc-2.12.1.so
004a7000-004aa000 rw-p 00000000 00:00 0 
004aa000-00592000 r-xp 00000000 08:02 1593219    /usr/lib/libgio-2.0.so.0.2600.1
00592000-00594000 r--p 000e7000 08:02 1593219    /usr/lib/libgio-2.0.so.0.2600.1
00594000-00595000 rw-p 000e9000 08:02 1593219    /usr/lib/libgio-2.0.so.0.2600.1
00595000-00596000 rw-p 00000000 00:00 0 
00596000-005d5000 r-xp 00000000 08:02 1589443    /usr/lib/libpango-1.0.so.0.2800.2
005d5000-005d6000 ---p 0003f000 08:02 1589443    /usr/lib/libpango-1.0.so.0.2800.2
005d6000-005d7000 r--p 0003f000 08:02 1589443    /usr/lib/libpango-1.0.so.0.2800.2
005d7000-005d8000 rw-p 00040000 08:02 1589443    /usr/lib/libpango-1.0.so.0.2800.2
005d8000-006a5000 r-xp 00000000 08:02 1916969    /lib/libglib-2.0.so.0.2600.1
006a5000-006a6000 r--p 000cc000 08:02 1916969    /lib/libglib-2.0.so.0.2600.1
006a6000-006a7000 rw-p 000cd000 08:02 1916969    /lib/libglib-2.0.so.0.2600.1
006a7000-006af000 r-xp 00000000 08:02 1594362    /usr/lib/libXrender.so.1.3.0
006af000-006b0000 r--p 00007000 08:02 1594362    /usr/lib/libXrender.so.1.3.0
006b0000-006b1000 rw-p 00008000 08:02 1594362    /usr/lib/libXrender.so.1.3.0
006b1000-006cb000 r-xp 00000000 08:02 1122907    /lib/libgcc_s.so.1
006cb000-006cc000 r--p 00019000 08:02 1122907    /lib/libgcc_s.so.1
006cc000-006cd000 rw-p 0001a000 08:02 1122907    /lib/libgcc_s.so.1
006cd000-006f1000 r-xp 00000000 08:02 1917004    /lib/libexpat.so.1.5.2
006f1000-006f3000 r--p 00024000 08:02 1917004    /lib/libexpat.so.1.5.2
006f3000-006f4000 rw-p 00026000 08:02 1917004    /lib/libexpat.so.1.5.2
006f4000-00700000 r-xp 00000000 08:02 1592630    /usr/lib/libXi.so.6.1.0
00700000-00701000 r--p 0000b000 08:02 1592630    /usr/lib/libXi.so.6.1.0
00701000-00702000 rw-p 0000c000 08:02 1592630    /usr/lib/libXi.so.6.1.0
00702000-00708000 r-xp 00000000 08:02 1591940    /usr/lib/libXrandr.so.2.2.0
00708000-00709000 r--p 00005000 08:02 1591940    /usr/lib/libXrandr.so.2.2.0
00709000-0070a000 rw-p 00006000 08:02 1591940    /usr/lib/libXrandr.so.2.2.0
0070a000-00712000 r-xp 00000000 08:02 1590948    /usr/lib/libXcursor.so.1.0.2
00712000-00713000 r--p 00007000 08:02 1590948    /usr/lib/libXcursor.so.1.0.2
00713000-00714000 rw-p 00008000 08:02 1590948    /usr/lib/libXcursor.so.1.0.2
00714000-0071b000 r-xp 00000000 08:02 1591901    /usr/lib/libSM.so.6.0.1
0071b000-0071c000 r--p 00006000 08:02 1591901    /usr/lib/libSM.so.6.0.1
0071c000-0071d000 rw-p 00007000 08:02 1591901    /usr/lib/libSM.so.6.0.1
0071d000-00727000 r-xp 00000000 08:02 1593423    /usr/lib/libpangocairo-1.0.so.0.2800.2
00727000-00728000 r--p 00009000 08:02 1593423    /usr/lib/libpangocairo-1.0.so.0.2800.2
00728000-00729000 rw-p 0000a000 08:02 1593423    /usr/lib/libpangocairo-1.0.so.0.2800.2
0072a000-0072d000 r-xp 00000000 08:02 1592101    /usr/lib/libgthread-2.0.so.0.2600.1
0072d000-0072e000 r--p 00003000 08:02 1592101    /usr/lib/libgthread-2.0.so.0.2600.1
0072e000-0072f000 rw-p 00004000 08:02 1592101    /usr/lib/libgthread-2.0.so.0.2600.1
0072f000-00786000 r-xp 00000000 08:02 1594395    /usr/lib/libtiff.so.4.3.3
00786000-00787000 ---p 00057000 08:02 1594395    /usr/lib/libtiff.so.4.3.3
00787000-00789000 r--p 00057000 08:02 1594395    /usr/lib/libtiff.so.4.3.3
00789000-0078a000 rw-p 00059000 08:02 1594395    /usr/lib/libtiff.so.4.3.3
0078a000-0078c000 r-xp 00000000 08:02 1591913    /usr/lib/libXcomposite.so.1.0.0
0078c000-0078d000 r--p 00001000 08:02 1591913    /usr/lib/libXcomposite.so.1.0.0
0078d000-0078e000 rw-p 00002000 08:02 1591913    /usr/lib/libXcomposite.so.1.0.0
0078e000-00790000 r-xp 00000000 08:02 1594356    /usr/lib/libXdamage.so.1.1.0
00790000-00791000 r--p 00001000 08:02 1594356    /usr/lib/libXdamage.so.1.1.0
00791000-00792000 rw-p 00002000 08:02 1594356    /usr/lib/libXdamage.so.1.1.0
00792000-00796000 r-xp 00000000 08:02 1594353    /usr/lib/libXfixes.so.3.1.0
00796000-00797000 r--p 00003000 08:02 1594353    /usr/lib/libXfixes.so.3.1.0
00797000-00798000 rw-p 00004000 08:02 1594353    /usr/lib/libXfixes.so.3.1.0Aborted
briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 672
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

Post by briceandre »

Your problem is here :

Code: Select all

void MyDlg::OnOK(wxCommandEvent& event)
{
        Destroy();
        SetReturnCode(1);
}
You should probably do something like

Code: Select all

void MyDlg::OnOK(wxCommandEvent& event)
{
        EndModal(1);
}
Same applies to OnCancel
vid512
Experienced Solver
Experienced Solver
Posts: 55
Joined: Mon Feb 08, 2010 10:16 am

Post by vid512 »

Thanks, that's it.

However, wxGTK should IMO still at least catch this error in its assert, not let it pass to glibc assert / segfault.
briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 672
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

Post by briceandre »

First, are you running a debug version ? if no, you will not get asserts.

Second, it's not common to put an assert in destructor to check that a double destruction occurs.... And even if you put such an assert, I don't know how you can implement it as object memory is released after first destruction. So, where do you put information allowing you to detect that a second destruction occurs ?
vid512
Experienced Solver
Experienced Solver
Posts: 55
Joined: Mon Feb 08, 2010 10:16 am

Post by vid512 »

Yes, this happens in debug version. Release version segfaults, as expected.

According to wxWindow::Destroy() description, this should only schedule dialog destruction for later, so checking for double scheduling should be possible.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Post by PB »

The ASSERT on MSW (using MSVC in Debug build) comes from CRT memory manager, so it's not wxWidgets thing but a compiler one.

What I don't understand is why in this code OnCancel is not called even when I click on the close button or pressing Esc is not handled despite the SetEscapeId(wxID_CANCEL)?.

Code: Select all

#include <wx/wx.h>

class MyApp: public wxApp
{
    virtual bool OnInit();
};

IMPLEMENT_APP(MyApp)

class MyDlg: public wxDialog
{
protected:
        void OnOK(wxCommandEvent& event);
        void OnCancel(wxCommandEvent& event);
public:
        MyDlg();        
        DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(MyDlg, wxDialog)
        EVT_BUTTON(wxID_CANCEL, MyDlg::OnCancel)
        EVT_BUTTON(wxID_OK, MyDlg::OnOK)
END_EVENT_TABLE()

MyDlg::MyDlg()
:wxDialog(0, -1, wxT("Dialog"), wxDefaultPosition, wxSize(200, 100))
{
        new wxStaticText(this, -1, wxT("Text"), wxPoint(0, 0));
        new wxButton(this, wxID_OK, wxT("&OK"), wxPoint(0, 30), wxSize(40, 30));
        SetEscapeId(wxID_CANCEL);
        SetFocus();
}

void MyDlg::OnOK(wxCommandEvent& event)
{        
    EndModal(1);           
}

void MyDlg::OnCancel(wxCommandEvent& event)
{        
    EndModal(0);
}

bool MyApp::OnInit()
{
        MyDlg dlg;
        if (dlg.ShowModal())
            wxMessageBox(wxT("true"));
        else
            wxMessageBox(wxT("false"));

        return false;
} 
Last edited by PB on Mon Feb 28, 2011 10:06 am, edited 2 times in total.
vid512
Experienced Solver
Experienced Solver
Posts: 55
Joined: Mon Feb 08, 2010 10:16 am

Post by vid512 »

There is no assert on wxMSW, only on wxGTK. And that's exactly the problem - IMO wxGTK *should* catch this error itself, if that is possible.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Post by PB »

vid512 wrote:There is no assert on wxMSW, only on wxGTK. And that's exactly the problem - IMO wxGTK *should* catch this error itself, if that is possible.
As I wrote above, it's not caught by wxWidgets but by MSVC CRT.
Image

What compiler do you use there, probably not MSVC, right? Because MSVC refuses even to compile the code you have posted (missing a return call from MyApp::OnInit()).
briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 672
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

Post by briceandre »

According to wxWindow::Destroy() description, this should only schedule dialog destruction for later, so checking for double scheduling should be possible.
If you shedule a double destruction, yes, it could be checked, and maybe it is, I don't know.

But, in your code, you have a schedule destruction that occurs first, and an immediate one on which wxWidgets has no possibility to interact (at least, not without redefining all delete operators and doing some checks in memory management).
briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 672
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

Post by briceandre »

What compiler do you use there, probably not MSVC, right? Because MSVC refuses even to compile the code you have posted (missing a return call from MyApp::OnInit()).
As he is running under linux, I suppose he uses gcc. And I agree with you, according to his stack trace, his assert does not come from wx, but from an internal test in his libcpp.
vid512
Experienced Solver
Experienced Solver
Posts: 55
Joined: Mon Feb 08, 2010 10:16 am

Post by vid512 »

PB: You're right. Seems in my Windows test I was linking to non-debug version of MSVCRT even in debug build. I'm in hurry a bit right now, so I can't test now.

briceandre: OK, I understand.
Post Reply