From a1326dc31a0540f24079a9a7591a08447ef55de7 Mon Sep 17 00:00:00 2001 From: Mariotaku Date: Mon, 4 Jul 2022 19:48:27 +0900 Subject: [PATCH] fix(fragment): memory leak of fragments #3438 (#3442) --- .../others/fragment/lv_example_fragment_1.c | 11 +++++++ .../others/fragment/lv_example_fragment_2.c | 11 +++++++ .../others/fragment/lv_fragment_manager.c | 32 ++++++++++--------- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/examples/others/fragment/lv_example_fragment_1.c b/examples/others/fragment/lv_example_fragment_1.c index 8be874988..9e5912449 100644 --- a/examples/others/fragment/lv_example_fragment_1.c +++ b/examples/others/fragment/lv_example_fragment_1.c @@ -10,6 +10,8 @@ static void sample_fragment_ctor(lv_fragment_t * self, void * args); static lv_obj_t * sample_fragment_create_obj(lv_fragment_t * self, lv_obj_t * parent); +static void sample_container_del(lv_event_t * e); + static lv_obj_t * root = NULL; struct sample_fragment_t { @@ -28,6 +30,9 @@ void lv_example_fragment_1(void) root = lv_obj_create(lv_scr_act()); lv_obj_set_size(root, LV_PCT(100), LV_PCT(100)); lv_fragment_manager_t * manager = lv_fragment_manager_create(NULL); + /* Clean up the fragment manager before objects in containers got deleted */ + lv_obj_add_event_cb(root, sample_container_del, LV_EVENT_DELETE, manager); + lv_fragment_t * fragment = lv_fragment_create(&sample_cls, "Fragment"); lv_fragment_manager_replace(manager, fragment, &root); } @@ -46,4 +51,10 @@ static lv_obj_t * sample_fragment_create_obj(lv_fragment_t * self, lv_obj_t * pa return label; } +static void sample_container_del(lv_event_t * e) +{ + lv_fragment_manager_t * manager = (lv_fragment_manager_t *) lv_event_get_user_data(e); + lv_fragment_manager_del(manager); +} + #endif diff --git a/examples/others/fragment/lv_example_fragment_2.c b/examples/others/fragment/lv_example_fragment_2.c index 648350ae1..c6a3e44c9 100644 --- a/examples/others/fragment/lv_example_fragment_2.c +++ b/examples/others/fragment/lv_example_fragment_2.c @@ -14,6 +14,8 @@ static void sample_push_click(lv_event_t * e); static void sample_pop_click(lv_event_t * e); +static void sample_container_del(lv_event_t * e); + static void sample_fragment_inc_click(lv_event_t * e); typedef struct sample_fragment_t { @@ -54,6 +56,9 @@ void lv_example_fragment_2(void) lv_obj_set_grid_cell(pop_btn, LV_GRID_ALIGN_END, 1, 1, LV_GRID_ALIGN_CENTER, 1, 1); lv_fragment_manager_t * manager = lv_fragment_manager_create(NULL); + /* Clean up the fragment manager before objects in containers got deleted */ + lv_obj_add_event_cb(root, sample_container_del, LV_EVENT_DELETE, manager); + int depth = 0; lv_fragment_t * fragment = lv_fragment_create(&sample_cls, &depth); lv_fragment_manager_push(manager, fragment, &container); @@ -106,6 +111,12 @@ static void sample_pop_click(lv_event_t * e) lv_fragment_manager_pop(manager); } +static void sample_container_del(lv_event_t * e) +{ + lv_fragment_manager_t * manager = (lv_fragment_manager_t *) lv_event_get_user_data(e); + lv_fragment_manager_del(manager); +} + static void sample_fragment_inc_click(lv_event_t * e) { sample_fragment_t * fragment = (sample_fragment_t *) lv_event_get_user_data(e); diff --git a/src/extra/others/fragment/lv_fragment_manager.c b/src/extra/others/fragment/lv_fragment_manager.c index 4a301345f..e8ee84f49 100644 --- a/src/extra/others/fragment/lv_fragment_manager.c +++ b/src/extra/others/fragment/lv_fragment_manager.c @@ -127,23 +127,25 @@ void lv_fragment_manager_remove(lv_fragment_manager_t * manager, lv_fragment_t * bool was_top = false; if(states->in_stack) { void * stack_top = _lv_ll_get_tail(&manager->stack); - lv_fragment_stack_item_t * stack = NULL; - _LV_LL_READ_BACK(&manager->stack, stack) { - if(stack->states == states) { - was_top = stack_top == stack; - void * stack_prev = _lv_ll_get_prev(&manager->stack, stack); + lv_fragment_stack_item_t * item = NULL; + _LV_LL_READ_BACK(&manager->stack, item) { + if(item->states == states) { + was_top = stack_top == item; + void * stack_prev = _lv_ll_get_prev(&manager->stack, item); if(!stack_prev) break; prev = ((lv_fragment_stack_item_t *) stack_prev)->states; break; } } - if(stack) { - _lv_ll_remove(&manager->stack, stack); + if(item) { + _lv_ll_remove(&manager->stack, item); + lv_mem_free(item); } } item_del_obj(states); item_del_fragment(states); _lv_ll_remove(&manager->attached, states); + lv_mem_free(states); if(prev && was_top) { item_create_obj(prev); } @@ -262,17 +264,17 @@ static lv_fragment_managed_states_t * fragment_attach(lv_fragment_manager_t * ma LV_ASSERT(manager); LV_ASSERT(fragment); LV_ASSERT(fragment->managed == NULL); - lv_fragment_managed_states_t * item = _lv_ll_ins_tail(&manager->attached); - lv_memset_00(item, sizeof(lv_fragment_managed_states_t)); - item->cls = fragment->cls; - item->manager = manager; - item->container = container; - item->instance = fragment; - fragment->managed = item; + lv_fragment_managed_states_t * states = _lv_ll_ins_tail(&manager->attached); + lv_memset_00(states, sizeof(lv_fragment_managed_states_t)); + states->cls = fragment->cls; + states->manager = manager; + states->container = container; + states->instance = fragment; + fragment->managed = states; if(fragment->cls->attached_cb) { fragment->cls->attached_cb(fragment); } - return item; + return states; } #endif /*LV_USE_FRAGMENT*/