lvgl: Solve the memory leak of user data

Please forgive me, my network can’t connect to lvgl’s forum, so I’m tired of putting questions here.

/*Declare the type of the user data of object (can be e.g. `void *`, `int`, `struct`)*/
typedef void * lv_obj_user_data_t;

typedef struct _lv_obj_t
{
    //Other members
#if LV_USE_USER_DATA
    lv_obj_user_data_t user_data; /**< Custom user data for object. */
#endif

} lv_obj_t;

Object has members that manage user data. It is very useful for function expansion. Although we can determine the type of data, we do not have a proper way to release the user data when the object is deleted. This requires us to spend extra resources to record and manage these user data to avoid memory leakage. Especially when objects nesting level is very deep, the problem is more troublesome. I think we need to provide an interface function to improve this problem.


//In lv_conf.h file //////////////////////////////////////////////////

/*1: Add a `user_data` to drivers and objects*/
#define LV_USE_USER_DATA        1

#if LV_USE_USER_DATA
/*Declare the type of the user data of object (can be e.g. `void *`, `int`, `struct`)*/
typedef void * lv_obj_user_data_t;
#define LV_USER_DATA_FREE_INCLUDE  "something.h"       /*Header for user data free  function*/
#define LV_USER_DATA_FREE  (user_data_free)     /*Invoking for user data free  function */
#endif

//in something.c file ////////////////////////////////////////////////
void user_data_free(lv_obj_user_data_t & user_data)
{
// free data
}

//in lv_obj.c file //////////////////////////////////////////////////////

#if LV_USE_USER_DATA
#include LV_USER_DATA_FREE_INCLUDE  
#endif 

/**
 * Delete 'obj' and all of its children
 * @param obj pointer to an object to delete
 * @return LV_RES_INV because the object is deleted
 */
lv_res_t lv_obj_del(lv_obj_t * obj)
{
//Other code
#if LV_USE_USER_DATA
    LV_USER_DATA_FREE(obj->user_data);
#endif 
}

If there is no problem in this way, I can create a pull request.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 16 (15 by maintainers)

Most upvoted comments

I agree it’s not ideal but rather a quick fix to have something.

IMO the proper solution is to free the user data in LV_EVENT_DELETE. It needs you to write event_cb for every object with custom user data but

  • if you already have an even_cb for that object it’s easy to add another if(e == LV_EVENT_DELETE)
  • if you don’t have event_cb you can add a my_free_event_cb.

I see the issue and it’s really an ugly situation. Creating event functions for a lot of objects only for LV_EVENT_DELTE is really tedious and unpleasant.

I can’t imagine a better solution and your suggestion seems simple and elegant.

Only a minor thing: let’s pass obj to LV_USER_DATA_FREE instead of obj->user_data because it’s easy to get user_data in the function too but obj might mean a useful context.

So if @embeddedt also agrees, please send a PR.

@amirgon could this custom “user data free” function be useful for Micropython?