首页 > 系统相关 >lvgl中存在的内存泄漏问题

lvgl中存在的内存泄漏问题

时间:2024-12-13 15:20:44浏览次数:4  
标签:泄漏 style set obj used lv LV 内存 lvgl

此篇文章在2024年5月24日被记录

在lvgl中,当两个页面之间互相切换时,先将第一个页面的控件全部删除,在创建新页面的控件,但是有时执行后会发现会出现内存泄漏:两个页面来回切换,内存占用不断提高,直到卡死。

1、情况复现

使用最简单的方式复现问题,模拟器新建两个页面,每个页面在创建时新建一个style对控件进行修饰,不断切换页面后,内存占用会不断升高
现象截图:

img

测试代码:

static lv_style_t style ;
static lv_obj_t * page1_obj ;
static lv_obj_t * page2_obj ;
static uint8_t page = 0 ;
void log_get_lvgl_mem(void)
{
    lv_mem_monitor_t mon;
    lv_mem_monitor(&mon);
    uint32_t used_size = mon.total_size - mon.free_size;
    uint32_t used_kb = used_size / 1024;
    uint32_t used_kb_tenth = (used_size - (used_kb * 1024)) / 102;
    printf("%"LV_PRIu32 ".%"LV_PRIu32 " kB used (%d %%)\n"
                            "%d%% frag.",
                            used_kb, used_kb_tenth, mon.used_pct,
                            mon.frag_pct);
}
static void event_handler(lv_event_t * e)
{
    lv_obj_t * obj = lv_event_get_target(e);
    lv_event_code_t code = lv_event_get_code(e);
    if(LV_EVENT_CLICKED == code)
    {
        // lv_style_reset(&style);
        if(0 == page)
        {
            page = 1 ;
            lv_obj_clean(lv_scr_act());
            test_creaty_page_2();
            log_get_lvgl_mem();
            printf("\r\nchange to page2\r\n");
        }
        else if(1 == page)
        {
            page = 0 ;
            lv_obj_clean(lv_scr_act());
            test_creaty_page_1();
            log_get_lvgl_mem();
            printf("\r\nchange to page1\r\n");
        }
        else
        {
            printf("error!\r\n");
        }
    }
}

void test_creaty_page_1(void)
{
    lv_style_init(&style);
    lv_style_reset(&style);
    lv_style_set_radius(&style, 10);
    lv_style_set_border_side(&style, LV_BORDER_SIDE_NONE);
    lv_style_set_bg_opa(&style, LV_OPA_COVER);
    lv_style_set_bg_color(&style, lv_color_make(255, 0, 0));
    page1_obj= lv_obj_create(lv_scr_act());
    lv_obj_add_style(page1_obj, &style, 0);
    lv_obj_set_pos(page1_obj, 0, 0);
    lv_obj_set_size(page1_obj, 200, 200);
    lv_obj_add_event_cb(page1_obj, event_handler, LV_EVENT_CLICKED, NULL);
}
void test_creaty_page_2(void)
{
    lv_style_init(&style);
    lv_style_reset(&style);
    lv_style_set_radius(&style, 10);
    lv_style_set_border_side(&style, LV_BORDER_SIDE_NONE);
    lv_style_set_bg_opa(&style, LV_OPA_COVER);
    lv_style_set_bg_color(&style, lv_color_make(0, 255, 0));
    page2_obj= lv_obj_create(lv_scr_act());
    lv_obj_add_style(page2_obj, &style, 0);
    lv_obj_set_pos(page2_obj, 0, 0);
    lv_obj_set_size(page2_obj, 200, 200);
    lv_obj_add_event_cb(page2_obj, event_handler, LV_EVENT_CLICKED, NULL);
}

2、解决办法

每次在页面切换时,使用接口将style其释放
解决代码:
取消注释event_handler中的lv_style_reset(&style);
现象:

img

3、总结

  • 造成内存泄露的核心原因是用户创建的style没有释放,因此在页面切换时不要忘记释放用户定义的style
  • 如果这个style修饰了多个对象,切换界面时释放style仍然会造成内存泄漏,因此在动态界面切换过程中,一个style最好只用来修饰一个界面,除非你知道你正在做什么
  • lvgl的style注释中也详细交代了Do not call lv_style_init on styles that already have some properties because this function won't free the used memory, just sets a default state for the style. In other words be sure to initialize styles only once!
  • 在开发阶段可以尽量多的依赖lvgl的调试宏开关
    • ·#define LV_USE_LOG 1 开启log开关
    • ·#define LV_USE_ASSERT_MALLOC 1 如果内存耗尽,会进入断言
    • ·define LV_USE_ASSERT_STYLE 1 如果出现了style重新初始化,会打印log提醒(本文核心)

标签:泄漏,style,set,obj,used,lv,LV,内存,lvgl
From: https://www.cnblogs.com/shumei52/p/18605051

相关文章

  • linux mm 之 FLATMEM 平坦内存模型
    把物理内存当作一片地址连续的存储空间,内核将这块连续的内存空间分为一页一页的内存块structpage。最早的内存模型,管理1G以下的内存时足够高效,可以虚拟地址与物理地址直接映射,它只适合管理一整块连续的物理内存。当大于1G且多块非连续的物理内存时,会造成内存空洞浪费内存空......
  • APP 内存泄露优化
    原理https://juejin.cn/post/6864492188404088846分析我的APP主要的VC路径如下:如果没有内存泄露的话,我们从一个VC_A开始push一个VC_B,无论在VC_B操作了什么,pop回到VC_A,这个时候的内存大小应该和VC_A在puhsVC_B的时候是一样大的。如图:页面结构:曲谱列表push曲谱详情->.........
  • 面试必会(嵌入式)-C语言面试高频(内存管理)
    1.(内存)堆和栈的区别⭐堆栈空间分配不同:栈由操作系统自动进行分配和释放,用于存放函数的参数值、局部变量的值等,具有高效性。堆:一般由程序员手动进行分配和释放,效率比栈低很多。data数据区:存放全局变量,静态变量。堆栈缓存方式不同:栈使用一级缓存,存储在处理器核心中,调用完......
  • C语言(内存管理)
    main函数原型定义:main函数有多种定义格式,main函数也是函数,函数相关的结论对main函数也有效(也可以定义main函数的函数指针)。main函数的完整写法:intmain(intargc,char*argv[]){}intmain(intargc,char**argv){}扩展写法:main(){}等价intmain(){}intmain......
  • 转载:【AI系统】内存分配算法
    本文将介绍AI编译器前端优化部分的内存分配相关内容。在AI编译器的前端优化中,内存分配是指基于计算图进行分析和内存的管理,而实际上内存分配的实际执行是在AI编译器的后端部分完成的。本文将包括三部分内容,分别介绍模型和硬件的内存演进,内存的划分与复用好处,节省内存的算法......
  • RocksDB 内存超限问题剖析
    作者:来自vivo互联网服务器团队-ZengLuobin在使用RocksDB存储引擎的过程中,有部分开发者遇到了内存使用超出预期的情况。本文针对这一问题展开了深入分析,从内存使用原理、RocksDB内存管理机制、常见内存使用问题等方面进行了详细探讨,并提出了相应的解决方案和优化建议,希望......
  • 排查cpu占用率高及堆内存溢出
    1.排查cpu占用过高1.输入top命令查看cpu占用最高的进程(如pid:2308)2.查看哪个线程占用cpu最高ps-mp2308-oTHREAD,tid,time(如线程TID占用cpu占用最高:2320)3.把TID2320转为16进制,printf"%x\n"2320(返回910)4.拉出指定线程的堆栈信息:jstack2308|grep910-A10......
  • 转载:【AI系统】内存分配算法
    本文将介绍AI编译器前端优化部分的内存分配相关内容。在AI编译器的前端优化中,内存分配是指基于计算图进行分析和内存的管理,而实际上内存分配的实际执行是在AI编译器的后端部分完成的。本文将包括三部分内容,分别介绍模型和硬件的内存演进,内存的划分与复用好处,节省内存的算法......
  • 如何在 Java 中进行内存泄漏分析?
    如何在Java中进行内存泄漏分析?内存泄漏是指程序中无法访问的对象仍然被占用内存,导致内存无法回收,最终导致内存不足、程序崩溃等问题。Java中的内存泄漏通常与垃圾回收机制的工作方式相关,虽然JVM会自动管理内存,但是如果程序设计不当,仍然可能发生内存泄漏。以下是一些常用的......
  • 转载:【AI系统】内存分配算法
    本文将介绍AI编译器前端优化部分的内存分配相关内容。在AI编译器的前端优化中,内存分配是指基于计算图进行分析和内存的管理,而实际上内存分配的实际执行是在AI编译器的后端部分完成的。本文将包括三部分内容,分别介绍模型和硬件的内存演进,内存的划分与复用好处,节省内存的算法......