11-13-2012 08:30 AM
Hello all,
I just stumbled upon a problem that seems too simple to be true. If I call DiscardCtrl from _that_ control callback, or if I call it from the panel callback without swallowing the even, I get a general protection fault.
Here's an example. To test it, double click on the control and it crashes. If you double click on the panel or use "return 1", no problem:
#include <cvirte.h> #include <utility.h> static int CtrlSlide=0, StyleIndex=-1;
static int AuthorizedStyles[]={ // Should work on all of those
CTRL_NUMERIC_THERMOMETER,
CTRL_NUMERIC_TANK,
CTRL_NUMERIC_GAUGE,
CTRL_NUMERIC_METER,
CTRL_NUMERIC_KNOB,
CTRL_NUMERIC_DIAL,
CTRL_NUMERIC_VSLIDE,
CTRL_NUMERIC_HSLIDE,
CTRL_NUMERIC_FLAT_VSLIDE,
CTRL_NUMERIC_FLAT_HSLIDE,
CTRL_NUMERIC_LEVEL_VSLIDE,
CTRL_NUMERIC_LEVEL_HSLIDE,
CTRL_NUMERIC_POINTER_VSLIDE,
CTRL_NUMERIC_POINTER_HSLIDE,
CTRL_NUMERIC_THERMOMETER_LS,
CTRL_NUMERIC_TANK_LS,
CTRL_NUMERIC_GAUGE_LS,
CTRL_NUMERIC_METER_LS,
CTRL_NUMERIC_KNOB_LS,
CTRL_NUMERIC_DIAL_LS,
CTRL_NUMERIC_LEVEL_VSLIDE_LS,
CTRL_NUMERIC_LEVEL_HSLIDE_LS,
CTRL_NUMERIC_POINTER_VSLIDE_LS,
CTRL_NUMERIC_POINTER_HSLIDE_LS
};
static char* StrStyles[]={
"THERMOMETER",
"TANK",
"GAUGE",
"METER",
"KNOB",
"DIAL",
"VSLIDE",
"HSLIDE",
"FLAT_VSLIDE",
"FLAT_HSLIDE",
"LEVEL_VSLIDE",
"LEVEL_HSLIDE",
"POINTER_VSLIDE",
"POINTER_HSLIDE",
"THERMOMETER_LS",
"TANK_LS",
"GAUGE_LS",
"METER_LS",
"KNOB_LS",
"DIAL_LS",
"LEVEL_VSLIDE_LS",
"LEVEL_HSLIDE_LS",
"POINTER_VSLIDE_LS",
"POINTER_HSLIDE_LS"
};
int CVICALLBACK cb_TestSRP (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { switch (event) { case EVENT_RIGHT_CLICK: DoSomething(panel, control); break; } return 0; } int CVICALLBACK cb_QuitSRP (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { switch (event) { case EVENT_COMMIT: QuitUserInterface (0); break; } return 0; } int CVICALLBACK cbp_Change(int panel, int event, void *callbackData, int eventData1, int eventData2) { switch (event) { case EVENT_LEFT_DOUBLE_CLICK: if (CtrlSlide!=0) DiscardCtrl (panel, CtrlSlide); CtrlSlide = NewCtrl (panel, AuthorizedStyles[(++StyleIndex)%(sizeof(AuthorizedStyles)/4)], "", 50, 80); SetCtrlAttribute (panel, CtrlSlide, ATTR_CALLBACK_FUNCTION_POINTER, cb_TestSRP); SetCtrlAttribute (panel, CtrlSlide, ATTR_LABEL_TEXT, StrStyles[StyleIndex%(sizeof(AuthorizedStyles)/4)]); return 0; // Change it to 1 and there's no problem } return 0; } int main (int argc, char *argv[]) { if (InitCVIRTE (0, argv, 0) == 0) return -1; /* out of memory */ int Pnl = NewPanel (0, "Test slide popup", 100, 100, 300, 300); int CtrlQuit= NewCtrl (Pnl, CTRL_ROUNDED_COMMAND_BUTTON, "QUIT", 0, 0); SetCtrlAttribute (Pnl, CtrlQuit, ATTR_VISIBLE, 0); SetCtrlAttribute (Pnl, CtrlQuit, ATTR_CALLBACK_FUNCTION_POINTER, cb_QuitSRP); SetPanelAttribute(Pnl, ATTR_CLOSE_CTRL, CtrlQuit); SetPanelAttribute(Pnl, ATTR_CALLBACK_FUNCTION_POINTER, cbp_Change); cbp_Change(Pnl, EVENT_LEFT_DOUBLE_CLICK, NULL, 0, 0); DisplayPanel(Pnl); RunUserInterface(); return 0; }
Solved! Go to Solution.
11-13-2012 08:34 AM
The problem can be 'solved' reading the help :
You cannot discard a control in the callback function for the control, except when responding to the EVENT_COMMIT event. Discarding the control from its own callback function in response to other events might cause unpredictable behavior.
11-13-2012 08:44 AM
You may try use PostDeferredCall function for this purpose
11-13-2012 10:13 AM
OK, I wasn't too surprised about the control callback crash, but a little bit more when it happened in the panel callback...