wxDialog. Heap corruption on ShowModal. Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
klas.marcks
Knows some wx things
Knows some wx things
Posts: 42
Joined: Thu Mar 13, 2014 9:49 pm

wxDialog. Heap corruption on ShowModal.

Post by klas.marcks »

I'm running wxWidgets 3.1.1 on a Windows 10 Machine and I get a heap corruption when I try tp destroy
"chained" modal Dialogs (possibly because of lack of understanding of how wxYield and Destroy works).

The setting:
My main wxFrame has a child modal dialog opened and the user can connect to a server that performs calculation
by clicking a "calculate" button in the dialog (The dialog is created on the heap).

When "calculate" is clicked, a member function of the dialog makes the server request asynchronously and displays
a wxProgressDialog in the main thread like this:

Code: Select all

//...
wxProgressDialog dialog(_("Simulation status"), _("Connecting to server"), 100, nullptr, wxPD_CAN_ABORT | wxPD_APP_MODAL | wxPD_AUTO_HIDE);
bool isResultOk;

std::future<void> requestHandle = std::async(std::launch::async, [&isResultOk, &session]
{
    //Send http request using a previously defined session object
    isResultOk = session.SendSimulationRequest( equest );
});

// Pulse the dialog while waiting for response from request.
while(requestHandle.wait_for(std::chrono::milliseconds(20)) != std::future_status::ready)
{	
	dialog.Pulse();
	wxYield();
}

try
{
	requestHandle.get();
}
catch (...)
{
    //Handle exception
}
//...
Now, if isResultOk is false, this means that the server did not give a 200 reply and I want to delete the
wxProgressDialog and display the server response in a new dialog. This is where I get a heap corruption.
I do the following immediately after the code shown above:

Code: Select all

if(!isResultOk)
{
    //Destroy the wxProgressDialog. I want to remove it before next dialog is shown.
    dialog.Destroy();
    wxDialog excDlg(this, wxID_Any, _("Error sending simulation request"));
	excDlg.ShowModal(); //Heap corruption!!!
	return;
}
The discovery of the heap corruption is made in wxAppConsoleBase::DeletePendingObjects.
There is a comment in this function
// remove it from the list first so that if we get back here somehow
// during the object deletion (e.g. wxYield called from its dtor) we
// wouldn't try to delete it the second time
that is interesting since wxYield is called before this happens.

The corruption happens every time I run this code (when isResultOk is false).
My question: is there anything I have done here that can have corrupted the heap or should I look outside of the code
presented here?

Further info:
What is peculiar is that if I replace the wxDialog with a wxMessageDialog like this:

Code: Select all

if(!isResultOk)
{
    //Destroy the wxProgressDialog. I want to remove it before next dialog is shown.
    dialog.Destroy();
    wxMessageDialog messDlg(this, _("Calculation failed!"), _("Simulation progress"), wxOK);
	messDlg.ShowModal(); //NO CORRUPTION DETECTED!
	return;
}
there is no heap corruption (or it is at least not discovered at this point).
I have tried these two ways of executing the code many many times and the first always fails and the second always works.

Also: if I do not destory the dialog (or do it after the new message dialog is created) there is no detected corruption.

Code: Select all

if(!isResultOk)
{
    wxDialog excDlg(this, wxID_Any, _("Error sending simulation request"));
	excDlg.ShowModal(); //NO HEAP CORRUPTION, but dialog still shown. Annoying.
    dialog.Destroy();   //Moved destruction to last. Could skip this line.
	return;
}

I found a way to close the dialog before the new one is created by calling wxMessageDialog::Update(100).

Code: Select all

if(!isResultOk)
{
	//make sure dialog close
	dialog.Update(100);
    
    wxDialog excDlg(this, wxID_Any, _("Error sending simulation request"));
	excDlg.ShowModal(); //NO HEAP CORRUPTION.
	return;
}
The question remains: Am I still doing something unsafe with wxYield (or something else) even using the last piece of code?

Regards
Klas
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDialog. Heap corruption on ShowModal.

Post by doublemax »

Code: Select all

dialog.Destroy();
I haven't read everything is detail, but this line is always wrong. You can't delete a Dialog that was constructed on the stack.

Put the construction of the dialog in its own block so that it gets automatically destroyed when it goes out of scope. Or create it on the heap.
Use the source, Luke!
klas.marcks
Knows some wx things
Knows some wx things
Posts: 42
Joined: Thu Mar 13, 2014 9:49 pm

Re: wxDialog. Heap corruption on ShowModal.

Post by klas.marcks »

Many Thanks! Creating the dialog on the heap seems to have removed the heap corruption (who knows...?). Strange though that the dialog.Destroy() has not caused problems in general (had it on a few more places in the same file).

Regards
Klas
Post Reply