Hi all,
I’m new with LVGL so bear with me. I’m using LVGL 8.1 (git hash 77e76aab2153787142f98defca1e0df0392bf2ed).
While testing switching animations, I encountered a memory allocation failure. It looks like starting an animation allocates some memory that is not freed after deleting the animation.
The documentation does not mention anything else that needs to be done other than to call lv_anim_del(var, func);
This is what I’m seeing before and after creation/deletion of an animation. Is this a memory leak or am I missing something?
before create
used: 3552 ( 87 %), frag: 5 %, biggest free: 520
after create
used: 3804 ( 93 %), frag: 0 %, biggest free: 292
before delete
used: 3804 ( 93 %), frag: 0 %, biggest free: 292
after delete
used: 3588 ( 88 %), frag: 17 %, biggest free: 424
This is the code that produces the output above:
#define EXPLODE_ANIMATION_FRAME_COUNT (14u)
static const lv_img_dsc_t *explode_animation_frames[EXPLODE_ANIMATION_FRAME_COUNT] = {
&logo1, &logo2, &logo3, &logo4, &logo5, &logo6, &logo7,
&logo8, &logo9, &logo10, &logo11, &logo12, &logo13, &logo14,
};
static lv_anim_t m_animation;
static lv_obj_t *m_current_frame;
static void screen_create(void) {
log_info("Creating screen");
lv_mem_monitor_t mon;
lv_mem_monitor(&mon);
log_warning("before create");
log_warning("used: %6d (%3d %%), frag: %3d %%, biggest free: %6d",
(int)(mon.total_size - mon.free_size), mon.used_pct, mon.frag_pct,
(int)mon.free_biggest_size);
m_current_frame = lv_img_create(lv_scr_act());
lv_img_set_src(m_current_frame, explode_animation_frames[0]);
lv_obj_align(m_current_frame, LV_ALIGN_CENTER, 0, 0);
// Animation stuff
lv_anim_init(&m_animation);
lv_anim_set_exec_cb(&m_animation, animation_executor);
lv_anim_set_var(&m_animation, m_current_frame);
lv_anim_set_time(&m_animation, 400);
lv_anim_set_values(&m_animation, 0, EXPLODE_ANIMATION_FRAME_COUNT - 1);
if (lv_anim_start(&m_animation) == NULL) {
log_error("Failed to start animation");
}
lv_mem_monitor(&mon);
log_warning("after create");
log_warning("used: %6d (%3d %%), frag: %3d %%, biggest free: %6d",
(int)(mon.total_size - mon.free_size), mon.used_pct, mon.frag_pct,
(int)mon.free_biggest_size);
}
static void screen_update(void) {
// Nothing to do
}
static void screen_delete(void) {
log_info("Deleting screen");
lv_mem_monitor_t mon;
lv_mem_monitor(&mon);
log_warning("before delete");
log_warning("used: %6d (%3d %%), frag: %3d %%, biggest free: %6d",
(int)(mon.total_size - mon.free_size), mon.used_pct, mon.frag_pct,
(int)mon.free_biggest_size);
if (lv_anim_del(m_current_frame, animation_executor)) {
log_info("Screen deleted");
}
lv_obj_del(m_current_frame);
lv_mem_monitor(&mon);
log_warning("after delete");
log_warning("used: %6d (%3d %%), frag: %3d %%, biggest free: %6d",
(int)(mon.total_size - mon.free_size), mon.used_pct, mon.frag_pct,
(int)mon.free_biggest_size);
}
static void animation_executor(void * obj, int32_t param) {
log_trace("Animating screen");
int32_t new_frame = LV_CLAMP(0, param, EXPLODE_ANIMATION_FRAME_COUNT - 1);
lv_img_set_src(m_current_frame, explode_animation_frames[new_frame]);
}
Thank you for your help!
EDIT: Added the missing lv_obj_del(m_current_frame);
call as mentioned in the comments.