Page 1 of 1

wxButton->Disable(); throws read access violation exception

Posted: Fri Jul 26, 2019 7:57 am
by widgetMaster696969
Hi everyone,

I'm currently working on a streaming application that necessitates the use of certain buttons below where the stream appears. While the stream is buffering I would like to disable certain buttons. However, when I try to disable the buttons, Visual Studios throws an exception in window.h:

Code: Select all

Exception thrown at 0x0184B4F6 in myApp.exe: 0xC0000005: Access violation reading location 0xCDCDCDCD.
I read around a little and gathered that the parent wxFrame must also be disabled to disable a button within it? Anyway, I tried this and it didn't work either, resulting in a slightly different exception:

Code: Select all

Exception thrown at 0x015349E1 in myApp.exe: 0xC0000005: Access violation reading location 0xCDCDCE11.
My code is below. I've cut it down a lot to improve readability but please let me know if you think there is anything relevant that is missing and I will post it right away. Thanks in advance! :D

EDIT: devicePanel is the main panel that contains deviceContentPanel, a panel that itself contains within it vidStreamPanel and controlPanel, both of which are obviously children of deviceContentPanel.

Code: Select all

//view.h ============================================

//this is the panel that contains the panel containing the button named buttonSettings
class DevicePanel : public wxPanel 
{
public:
	wxPanel* deviceContentPanel;
	wxPanel* vidStreamPanel;
	wxPanel* controlPanel;
	wxBitmapButton* buttonSettings;
};

//device_view.cpp ===========================================

void DevicePanel::Init()
{
	drawControlPanel();
}

//this is the panel that contains the button named buttonSettings
void DevicePanel::drawControlPanel()
{
	controlPanel = new wxPanel(bla bla bla);
	controlPanel->SetSizer(exampleSizer);
	buttonSettings = createButton(controlPanel, "res/images/ic_settings.png", _("settings"), 101);
	buttonSettings->Connect(101, wxEVT_BUTTON, wxCommandEventHandler(DevicePanel::onSettingsClick), NULL, this);
}

void DevicePanel::onPlayStreamClick(wxCommandEvent &event)
{
	wxWindowBase * const parent = buttonSettings->GetParent(); //this line throws the second exception I mentioned in window.h
	if (parent->IsEnabled())
		parent->Disable();
        //the following line doesn't work but was a potential workaround I tried
	//buttonSettings->Disconnect(101, wxEVT_BUTTON, wxCommandEventHandler(DevicePanel::onSettingsClick), NULL, NULL); 
	buttonSettings->Disable(); // this line on its own throws the first exception I mentioned in window.h
}

Re: wxButton->Disable(); throws read access violation exception

Posted: Fri Jul 26, 2019 8:37 am
by Kvaz1r

Code: Select all

wxBitmapButton* buttonSettings = createButton(controlPanel, "res/images/ic_settings.png", _("settings"), 101);
That's wrong, here you create local variable not assign to member one.

Re: wxButton->Disable(); throws read access violation exception

Posted: Fri Jul 26, 2019 8:48 am
by widgetMaster696969
Oh sorry I actually copied old code which resulted in that line. I declare the button as a member of the class in the .h file, so that I can access it everywhere in the .cpp file. I'll edit the post. Thanks for catching that.

Re: wxButton->Disable(); throws read access violation exception

Posted: Fri Jul 26, 2019 8:59 am
by Kvaz1r
ok, where is stored and created controlPanel? Is it really reachable from handler?

Re: wxButton->Disable(); throws read access violation exception

Posted: Fri Jul 26, 2019 9:13 am
by widgetMaster696969
I've edited it again to show where the panels are declared. They are all initialized and drawn by the Init() function.

Re: wxButton->Disable(); throws read access violation exception

Posted: Fri Jul 26, 2019 9:30 am
by doublemax
What's inside the createButton() method?ยด
Can you use a debug build and create a proper stack trace?

I highly suggest to learn how to use a debugger. These kind of errors are usually very easy to detect and fix.

Re: wxButton->Disable(); throws read access violation exception

Posted: Fri Jul 26, 2019 9:46 am
by widgetMaster696969
Here is the createButton method:

Code: Select all

wxBitmapButton* DevicePanel::createButton(wxWindow* parent, wxString res, wxString text, int id)
{
	wxBitmap bmp(104, 32); 
	wxMemoryDC dc;
	dc.SelectObject(bmp);
	dc.SetBackground(*wxLIGHT_GREY_BRUSH);
	dc.Clear();
	dc.SetTextForeground(*wxBLACK);
	dc.DrawLabel(wxStripMenuCodes(text), GetResizeBitmap(res,24,24), wxRect(32, 0, 32, 32), wxALIGN_CENTRE);
	wxBitmapButton* ret = new wxBitmapButton(parent,id,bmp);
	return ret;
}
In terms of the callstack, I'm using Microsoft Visual Studios 2017, and the callstack isn't particularly helpful, showing only the line that I posted above in the original post (buttonSettings->Disable();) which leads to a call to to Disable() in line 633 of window.h. I'll post that code too:

Code: Select all

// returns true if window was enabled/disabled, false if nothing done          ==line 631==
virtual bool Enable( bool enable = true );                                                      ==line 632==
bool Disable() { return Enable(false); }                                                          ==line 633==

Re: wxButton->Disable(); throws read access violation exception

Posted: Fri Jul 26, 2019 10:46 am
by doublemax
The only way buttonSettings->Disable() can fail if is buttonSettings is not a valid pointer. But that should have been fixed by what Kvaz1r said.

In VS set a breakpoint after this line:

Code: Select all

buttonSettings = createButton(controlPanel, "res/images/ic_settings.png", _("settings"), 101);
and check the value of buttonSettings .

Also set a breakpoint before buttonSettings->Disable() and check if the value of buttonSettings is the same.

Re: wxButton->Disable(); throws read access violation exception

Posted: Mon Jul 29, 2019 6:16 am
by widgetMaster696969
This is incredibly embarrassing, but I see that the buttonSettings value accessed by the call to disable was one that I had duplicately declared in another part of my program, thus causing the crash.

Unfortunately, now the call to buttonSettings->Disable(); works without throwing exceptions, but it won't change anything about the button being clickable unless the parent window, too, is disabled, in which case every single button in the window (not just buttonSettings) won't perform any function. I've gotten around this by not using disable at all, and just connecting buttonSettings and the other ones I need when the stream is done buffering, but is there something I'm missing about ->Disable(); ? Why does it only work in tandem with a parent window? Does this mean any button should have it's own window around it if one would want to call ->Disable(); on the button?

Re: wxButton->Disable(); throws read access violation exception

Posted: Mon Jul 29, 2019 10:57 am
by doublemax
Just button->Disable() should be enough. For test, add that call directly after creating it and check if it works.