LVGL Freezing After Deleting and Recreating Same Object

Hi everyone,

I am currently running LVGL on version 8.2.0 and I did have some problems with the Message Box widget, it didn’t fit for us as the way it was designed, so I made my own Message Box by creating a container as the parent, and the labels and buttons as its children and it did work quite well.

We are using our Message Box to display custom Warnings and Errors related to our program for the user to see. In my code, I am using a single lv_obj_t* to hold the Message Box objec that is used for all of our displayed messages.

Since we use the same object, we did make sure that it can be created a single time, if an error occur it will only display the first error and the second one will only appear after the user hit the “Acknowledge” Button that has as an event to destroy the object.

It worked fine for us for a while, till someday we did deleted and created too many Message Boxes. We have lots of confirmations warnings in our code, as we were making our Message Boxes to appear, one time it did frozen our screen. We did repeat the issue several times to see if we could track it, and the only thing we did notice, was that after creating and deleting the Message Box around 40 to 50 times always, the screen freezes.

See below the function that we use to create the Message Box:

lv_obj_t* createMessageBoxOk(lv_obj_t* parent , char* content[6][100], lv_event_cb_t event, lv_event_code_t eventCode, void* variable){

    static lv_style_t styleContainer;
    lv_style_init(&styleContainer);
    lv_style_set_radius(&styleContainer, commonRadius);
    lv_style_set_bg_opa(&styleContainer, LV_OPA_COVER);
    lv_style_set_bg_color(&styleContainer, colorWhite);
    lv_style_set_bg_grad_color(&styleContainer, colorGray);
    lv_style_set_bg_grad_dir(&styleContainer, LV_GRAD_DIR_VER);
    lv_style_set_shadow_color(&styleContainer, colorBlack);
    lv_style_set_shadow_opa(&styleContainer, LV_OPA_COVER);
    lv_style_set_shadow_width(&styleContainer, 5);

    static lv_style_t styleTitle;
    lv_style_init(&styleTitle);
    lv_style_set_text_font(&styleTitle, &gill_sans_30);

    static lv_style_t styleText;
    lv_style_init(&styleText);
    lv_style_set_text_font(&styleText, &gill_sans_22);

    lv_obj_t* messageBox = lv_obj_create(parent);
    lv_obj_set_size(messageBox, 440, 240);
    lv_obj_add_style(messageBox, &styleContainer, LV_PART_MAIN);
    lv_obj_clear_flag(messageBox, LV_OBJ_FLAG_CLICKABLE);
    lv_obj_center(messageBox);

    lv_obj_t* labelTitle = lv_label_create(messageBox);
    lv_obj_add_style(labelTitle, &styleTitle, LV_STATE_DEFAULT);
    lv_label_set_text(labelTitle, content[0]);
    lv_obj_align(labelTitle, LV_ALIGN_TOP_MID, 0, 0.5*borderOffset);

    lv_obj_t* labelTextUpper = lv_label_create(messageBox);
    lv_obj_add_style(labelTextUpper, &styleText, LV_STATE_DEFAULT);
    lv_label_set_text(labelTextUpper, content[1]);
    lv_obj_align(labelTextUpper, LV_ALIGN_CENTER, 0, -2*borderOffset);

    lv_obj_t* labelTextMiddle = lv_label_create(messageBox);
    lv_obj_add_style(labelTextMiddle, &styleText, LV_STATE_DEFAULT);
    lv_label_set_text(labelTextMiddle, content[2]);
    lv_obj_align(labelTextMiddle, LV_ALIGN_CENTER, 0, -0.75*borderOffset);

    lv_obj_t* labelTextLower = lv_label_create(messageBox);
    lv_obj_add_style(labelTextLower,  &styleText, LV_STATE_DEFAULT);
    lv_label_set_text(labelTextLower,  content[3]);
    lv_obj_align(labelTextLower,  LV_ALIGN_CENTER, 0, 0.5*borderOffset);

    if(strcmp(content[2], "") == 0){
        lv_obj_align(labelTextUpper, LV_ALIGN_CENTER, 0, -1.25*borderOffset);
        lv_obj_align(labelTextLower, LV_ALIGN_CENTER, 0, 0.25*borderOffset);
    }

    static lv_style_t styleReference;
    lv_style_init(&styleReference);
    lv_style_set_radius(&styleReference, commonRadius);
    lv_style_set_bg_opa(&styleReference, LV_OPA_COVER);
    lv_style_set_bg_color(&styleReference, colorWhite);
    lv_style_set_bg_grad_color(&styleReference, colorGray);
    lv_style_set_bg_grad_dir(&styleReference, LV_GRAD_DIR_VER);

    lv_style_set_border_color(&styleReference, colorBlack);
    lv_style_set_border_opa(&styleReference, LV_OPA_100);
    lv_style_set_border_width(&styleReference, 2);

    lv_style_set_shadow_color(&styleReference, colorBlack);
    lv_style_set_shadow_opa(&styleReference, LV_OPA_COVER);
    lv_style_set_shadow_width(&styleReference, 5);
    lv_style_set_shadow_ofs_x(&styleReference, 2);
    lv_style_set_shadow_ofs_y(&styleReference, 2);

    static lv_style_t stylePressed;
    lv_style_init(&stylePressed);
    lv_style_set_transform_width(&stylePressed, -2);
    lv_style_set_transform_height(&stylePressed, -2); 

    lv_obj_t* buttonOk = lv_btn_create(messageBox);
    lv_obj_align(buttonOk, LV_ALIGN_BOTTOM_MID, 0, -borderOffset);
    lv_obj_set_size(buttonOk, mediumButtonSize, smallButtonSize);
    lv_obj_add_event_cb(buttonOk, event, eventCode, variable);
    lv_obj_add_style(buttonOk, &styleReference, LV_STATE_DEFAULT);
    lv_obj_add_style(buttonOk, &stylePressed, LV_STATE_PRESSED);

    lv_obj_t* labelButton = lv_label_create(buttonOk);
    lv_obj_center(labelButton);
    lv_obj_add_style(labelButton, &styleText, LV_STATE_DEFAULT);
    lv_label_set_text(labelButton, content[4]);

    return messageBox;

}

We send as arguments to the function the Screen to display the Message Box as parent, our message contents, and the event related arguments.

The event to delete the object is the following:

static void messageBoxOkEvent(lv_event_t* event) {
    lv_event_code_t code = lv_event_get_code(event);
    void* variable = lv_event_get_user_data(event);

    if(code == LV_EVENT_CLICKED) {

        gstPlay(SOUND_BUTTON);

        if(isError){isError = false;}
        if(isWarning){isWarning = false;}

        lv_obj_del(messageBox);
        flagIsMessageBox = false;
        
    }
}

We did try to delete by using lv_obj_del_async(), but it didn’t make any difference. I can’t tell what causes this issue, we only started seeing it a week ago (and we did start using this Message Box a month ago), but if I was to guess, I would say that we may be creating the Message Box object at a different memory location at every call (I already tried making it static but without success). It seems to be a memory issue, but we have a LOT of available memory, we are using the Colibri - IMX7 from Toradex, our code is on the A7 core (512MB NAND flash), so I wouldn’t say this is the issue. We also have as our Kernel a Linux Yocto image.

Would you have any ideas of what might be freezing our code? Maybe a cache from the deleted objects?

Thanl you for your time in advance.

Hi,

I believe it’s an out of memory issue. You an confirm it if you enable logging in lv_conf.h.

And indeed, I found a memory leak in your code:

lv_style_init drops the current content of the style and initializes it. So previous styles are not freed. You have a few options to fix it:

  • add flag in createMessageBoxOk like static bool styles_inited and use it to be sure you initialize the styles only once
  • use local style
  • initialize the styles on some other place that runs only once. E.g. have an initMessageBox function for style inits.

Hi @kisvegabor ,

Thank you very much for your answer, indeed we did have a memory issue, after coding more stuff, our program did freeze at boot if I tried to add more components and stuff, even if we still did have a lot of free memory. We did increase in our lv_conf.h the LV_MEM_SIZE from (2U * 64U * 1024U) to (4U * 64U * 1024U), could it impose any future problems?

After you telling me that our styles were not being deleted and instead we were creating multiples of the same, I did what you said about initializing them all at once. I appreciate your tips.

Thank you very much.

If the root of the issue is a memory leak, this will only hide the problem until all the memory is once again allocated. However, if you have a sufficiently complex UI (which sounds likely based on your description), this is probably the right solution.

I suggest enabling logging as LVGL can spot some style related memory leaks if LV_USE_ASSERT_STYLE is also enabled in lv_conf.h.