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

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
widgetMaster696969
In need of some credit
In need of some credit
Posts: 8
Joined: Wed Jul 24, 2019 7:38 am

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

Post 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
}
Last edited by widgetMaster696969 on Fri Jul 26, 2019 9:13 am, edited 3 times in total.
Kvaz1r
Super wx Problem Solver
Super wx Problem Solver
Posts: 357
Joined: Tue Jun 07, 2016 1:07 pm

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

Post 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.
widgetMaster696969
In need of some credit
In need of some credit
Posts: 8
Joined: Wed Jul 24, 2019 7:38 am

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

Post 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.
Kvaz1r
Super wx Problem Solver
Super wx Problem Solver
Posts: 357
Joined: Tue Jun 07, 2016 1:07 pm

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

Post by Kvaz1r »

ok, where is stored and created controlPanel? Is it really reachable from handler?
widgetMaster696969
In need of some credit
In need of some credit
Posts: 8
Joined: Wed Jul 24, 2019 7:38 am

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

Post by widgetMaster696969 »

I've edited it again to show where the panels are declared. They are all initialized and drawn by the Init() function.
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

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

Post 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.
Use the source, Luke!
widgetMaster696969
In need of some credit
In need of some credit
Posts: 8
Joined: Wed Jul 24, 2019 7:38 am

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

Post 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==
Last edited by catalin on Fri Jul 26, 2019 8:31 pm, edited 1 time in total.
Reason: code tags
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

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

Post 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.
Use the source, Luke!
widgetMaster696969
In need of some credit
In need of some credit
Posts: 8
Joined: Wed Jul 24, 2019 7:38 am

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

Post 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?
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

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

Post by doublemax »

Just button->Disable() should be enough. For test, add that call directly after creating it and check if it works.
Use the source, Luke!
Post Reply