What is the proper way to delete or hide container with children? lv_del_obj causes segmentation fault

Description

Erase a container without segmentation fault.

What MCU/Processor/Board and compiler are you using?

Atmel ARM32., arm-none-eabi-gcc.exe

What LVGL version are you using?

v7.7.2

What do you want to achieve?

I made a multi-tabbed screen. I like to put a temporary pop up container on top of it with buttons when I click on a text area. Inside the popup, I like to click a button in the popup to delete the container with the children buttons. The problem is that when I use lv_del_obj on the container of the buttons, I get a segmentation fault.
Q1) Why is there a segmentation fault?
Q2) What parent should I call with lv_cont_create: the tabbed view or lv_scr_act()?
Q3) What would the correct approach be to create and destroy this popup?

What have you tried so far?

I tried a simple lv_obj_clean on the parent container of the buttons. It erases all the buttons but leaves the parent container there.

I tried lv_obj_del_async(popupCont); and lv_obj_del(popupCont); which both give segmentation faults.

Code to reproduce

lv_obj_t * popupCont=NULL;

static void ta_event_cb(lv_obj_t* ta, lv_event_t e){
	if (e == LV_EVENT_RELEASED) {
               createPopup(lv_scr_act());
        }
}

void createPopup(lv_obj_t* h) {
	popupCont= lv_cont_create(h, NULL);
	/*lv_obj_set_pos(popupCont, 10, 5);*/
	lv_obj_set_pos(popupCont, 0, 0);
	lv_obj_set_size(popupCont, 780, 160+35);
        popupCont = lv_btn_create(popupCont, NULL);
	lv_obj_set_event_cb(cancelBtn, popupCancelCb);
}

static void popupCancelCb(lv_obj_t* btn, lv_event_t e) {
	if (e == LV_EVENT_SHORT_CLICKED || e == LV_EVENT_LONG_PRESSED_REPEAT) {
		lv_obj_clean(popupCont);
		lv_obj_del_async(popupCont);
	}
}

This appears to be working in the simulator. It might be an issue with your platform.

I did not put tabbed in these code snippets. Could that make the difference? I have made a copy from my embedded code into CodeBlocks where I cloned just the codeblocks demo project today. I get the segmentation in both systems.

I noticed that the segmentation fault comes from the second time I create the popup and try to delete it. Could you please try again? Thanks

Your code as-is does not compile (cancelBtn does not exist), so I had to tweak it a bit. The tweaked version appears to be running fine. Can you please post a code sample which is self-contained and compiles correctly? The changes might be what hides it from me.

void createPopup(lv_obj_t* h) {
	popupCont= lv_cont_create(h, NULL);
	/*lv_obj_set_pos(popupCont, 10, 5);*/
	lv_obj_set_pos(popupCont, 0, 0);
	lv_obj_set_size(popupCont, 780, 160+35);
    /*popupCont*/ cancelBtn  = lv_btn_create(popupCont, NULL);
	lv_obj_set_event_cb(cancelBtn, popupCancelCb);
}

Hello,
My apologies for the code that did not compile. I will not rewrite my code and post without compiling again.
I found some causes of my error in the bigger program. I did 3 reparations.

  1. I had some code outside of an if statement that filters out the kind of event in a callback. This code was acting on widgets that either did not exist yet or were destroyed by the lv_obj_del.
if (e == LV_EVENT_SHORT_CLICKED || e == LV_EVENT_LONG_PRESSED_REPEAT) {

2.Also, I made for sure that my container was deleted or created only once by A) setting the pointers to NULL after deletion and B) checking against NULL before creating.

  1. I think I have some confusion about the event types and which one is the best for me The events LV_EVENT_RELEASED and LV_EVENT_SHORT_CLICKED are not the same. I just had them in my code without paying attention of the difference. On the embedded device, I am not sure how many multiple events are fired when I press on the touch screen. I will read up on them some more.

For completeness sake, I post code to the above questions that does compile. There are no run functionality errors. Many thanks to those who helped out.


lv_obj_t * popupCont=NULL;


static void popupCancelCb(lv_obj_t* btn, lv_event_t e) {
	if (e == LV_EVENT_SHORT_CLICKED || e == LV_EVENT_LONG_PRESSED_REPEAT) {
		lv_obj_clean(popupCont);
		lv_obj_del_async(popupCont);
	}
}

void createPopup(lv_obj_t* h) {
	popupCont= lv_cont_create(h, NULL);
	lv_obj_set_pos(popupCont, 0, 0);
	lv_obj_set_size(popupCont, 300, 300);

    lv_obj_t* cancelBtn  = lv_btn_create(popupCont, NULL);
    lv_obj_t* label = lv_label_create(cancelBtn, NULL);
    lv_label_set_text(label, "cancel");
	lv_obj_set_event_cb(cancelBtn, popupCancelCb);
}


static void ta_event_cb(lv_obj_t* ta, lv_event_t e){
    if (e == LV_EVENT_RELEASED) {
        createPopup(lv_scr_act());
    }
}

/**********************
 *   GLOBAL FUNCTIONS
 **********************/
#if WIN32
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int nCmdShow)
#else
int main(int argc, char** argv)
#endif // WIN32
{
    /*Initialize LittlevGL*/
    lv_init();

    /*Initialize the HAL for LittlevGL*/
    hal_init();

    /*Check the themes too*/
    lv_disp_set_default(lv_windows_disp);


    lv_obj_t* ta0  = lv_textarea_create(lv_scr_act(), NULL);


    lv_textarea_set_text(ta0, "open the popup");
    lv_obj_set_event_cb(ta0, ta_event_cb);

    createPopup(lv_scr_act());

    /*Run the v7 demo*/
    /*lv_demo_widgets();*/

#if WIN32
    while(!lv_win_exit_flag) {
#else
    while(1) {
#endif // WIN32
        /* Periodically call the lv_task handler.
         * It could be done in a timer interrupt or an OS task too.*/
        lv_task_handler();
        usleep(1000);       /*Just to let the system breath*/
    }
    return 0;
}
1 Like

LV_EVENT_RELEASED fires whenever you release the object, whereas LV_EVENT_SHORT_CLICKED only fires if the object hasn’t been held down long enough to qualify as a “long press”.

Here is the docs page for the input events.