Discussion:
Event class derivation leads to illegal pointers
Jan Engelhardt
2014-08-08 02:47:56 UTC
Permalink
When running below's sample code (on wxGTK2-3.0.1, should that matter),
I observe, on stdout,

SetEO: 0x558450
GetEO: 0xa0
SetEO: 0x558450
GetEO: (nil)
SetEO: 0x558450
GetEO: 0x74

and that just can't be remotely right, however I don't see where the
problem originates. Bind() is typesafe (or so I thought) and the
compiler does not yield warnings. valgrind points to

==30299== Invalid read of size 8
==30299== at 0x40F0F2: FooEvent::GetThing() const (q.cpp:14)
==30299== by 0x40F117: F::F()::{lambda(FooEvent&)#1}::operator()(FooEvent&)
const (q.cpp:30)
==30299== by 0x40F93E: wxEventFunctorFunctor<wxEventTypeTag<FooEvent>,
F::F()::{lambda(FooEvent&)#1}>::operator()(wxEvtHandler*, wxEvent&)
(event.h:516)

but GetThing should be ok, because there is always a call to SetThing.


#include <wx/wx.h>
class T : public wxTextCtrl {
public:
T(wxWindow *);
};
class FooEvent : public wxCommandEvent {
private:
T *m_text;
public:
using wxCommandEvent::wxCommandEvent;
void SetThing(T *p) { m_text = p; };
T *GetThing(void) const { return m_text; };
};
wxDEFINE_EVENT(FOOEVENT, FooEvent);
T::T(wxWindow *p) : wxTextCtrl(p, wxID_ANY) {
Bind(wxEVT_TEXT, [this](wxCommandEvent &) {
FooEvent e(FOOEVENT, GetId());
e.SetThing(this);
printf("SetEO: %p\n", this);
wxPostEvent(this, e);
});
};
class F : public wxFrame {
public:
F(void) : wxFrame(NULL, wxID_ANY, "") {
auto t = new T(this);
Bind(FOOEVENT, [this](FooEvent &e) {
T *x = e.GetThing();
printf("GetEO: %p\n", x);
}, t->GetId());
};
};
class A : public wxApp {
public:
bool OnInit(void) { (new F)->Show(); return true; };
};
IMPLEMENT_APP(A);
--
Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.

To unsubscribe, send email to wx-users+***@googlegroups.com
or visit http://groups.google.com/group/wx-users
Vadim Zeitlin
2014-08-08 12:41:59 UTC
Permalink
On Fri, 8 Aug 2014 04:47:56 +0200 (CEST) Jan Engelhardt wrote:

JE> When running below's sample code (on wxGTK2-3.0.1, should that matter),
JE> I observe, on stdout,
JE>
JE> SetEO: 0x558450
JE> GetEO: 0xa0
JE> SetEO: 0x558450
JE> GetEO: (nil)
JE> SetEO: 0x558450
JE> GetEO: 0x74
JE>
JE> and that just can't be remotely right, however I don't see where the
JE> problem originates. Bind() is typesafe (or so I thought) and the
JE> compiler does not yield warnings.

You forgot to implement FooEvent::Clone(), so it's a kind of slicing
problem: when the event is copied internally, only its wxCommandEvent part
is copied.

Unfortunately this is impossible to fix at compile time because
wxCommandEvent is not (and can not be) an ABC, so Clone() can't be pure
virtual in it. If you had derived directly from wxEvent, the compiler would
have told you about the problem.

Regards,
VZ
--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/
Loading...