Sunrisepeak / opensource-community

Opensource Community
3 stars 0 forks source link

使用LVGL绘制图片时,多次重复创建img对象,会内存泄漏导致死机的问题 #6

Open sky-littlestar opened 1 month ago

sky-littlestar commented 1 month ago

Background | 背景

利用国民技术N32G452CEL7单片机MCU进行项目开发,通过LVGL图形库进行GUI的绘制,在绘制图片的过程中,重复调用lv_img_create(lv_scr_act());函数进行图形的绘制,最终由于内存泄漏导致死机

Describe | 问题描述

我要实现两张图片交替在同一位置交替显示,于是使用lv_img_create(lv_scr_act());函数,在同一个坐标不断绘制图片,最后导致死机的现象出现。随后添加了函数lv_obj_del(img),显示A图片时,把B图片删除,显示B图片时,把A图片删除,死机问题不再出现。伪代码如下(以下代码为正常代码,添加了删除函数,不会死机,后面复现,有不正常代码): static lv_obj_t* obj_wifisymbol = lv_img_create(lv_scr_act()); //开机初始化,先假设显示wifi图标,后边再根据实际情况判断 lv_img_set_src(obj_wifisymbol, &openwifi);
while(1) { if(GucWifi_State==1) //如果wifi为打开状态,添加打开wifi图标 {
lv_obj_del(obj_wifisymbol); //删除wifi关闭图标 obj_wifisymbol = lv_img_create(lv_scr_act());
lv_img_set_src(obj_wifisymbol, &openwifi); //添加openwifi图标 lv_obj_set_pos(obj_wifisymbol, 22, 69-lvgl_Height); //设置坐标 } else if(GucWifi_State==0) //如果wifi为关闭状态,添加关闭wifi图标 {
lv_obj_del(obj_wifisymbol); //删除wifi打开图标 obj_wifisymbol = lv_img_create(lv_scr_act()); lv_img_set_src(obj_wifisymbol, &closewifi); //添加关闭wifi图标 lv_obj_set_pos(obj_wifisymbol, 22, 69-lvgl_Height); //设置坐标 } } 此代码不会死机,但是如果没有lv_obj_del函数会死机,应该是堆空间不足造成的。

Desktop | 环境

MDK Keil 5.36 LVGL 8.3.9 C语言 C99标准

To Reproduce | 复现步骤

while(1) { if(GucWifi_State==1) //如果wifi为打开状态,添加打开wifi图标 {
obj_wifisymbol = lv_img_create(lv_scr_act());
lv_img_set_src(obj_wifisymbol, &openwifi); //添加openwifi图标 lv_obj_set_pos(obj_wifisymbol, 22, 69-lvgl_Height); //设置坐标 } else if(GucWifi_State==0) //如果wifi为关闭状态,添加关闭wifi图标 {
obj_wifisymbol = lv_img_create(lv_scr_act()); lv_img_set_src(obj_wifisymbol, &closewifi); //添加关闭wifi图标 lv_obj_set_pos(obj_wifisymbol, 22, 69-lvgl_Height); //设置坐标 } } 只创建,不删除,重复7-8次就会死机,如果添加删除函数,就一直不会死机

Expection | 预期结果

想探讨一个问题,为何申请的内存超出堆就会死机?即使发生内存泄漏,在内存中,堆空间和栈空间不是分开的吗?就算我的堆空间满了,但是栈空间依然可以给程序一定的运行空间,为何程序会出现无法运行的死机现象,这跟LVGL的内存管理有关系吗?

Solution by you | 已尝试的方案

Additional context | 额外补充

image 堆区和栈区是独立,为何内存泄漏导致的堆溢出会导致死机,应该栈区有空间可以运行下去的?

Sunrisepeak commented 1 month ago

这个循环的逻辑好像并不会交替图片, 是有前置条件吗, 以及图像源是文件还是直接存内存的呢

while(1)
{
  if(A)
  {
    A=lv_img_create(lv_scr_act());
  }
  if(B)
  {
    B=lv_img_create(lv_scr_act());
  }
}
sky-littlestar commented 1 month ago

这个循环的逻辑好像并不会交替图片, 是有前置条件吗, 以及图像源是文件还是直接存内存的呢

while(1)
{
  if(A)
  {
    A=lv_img_create(lv_scr_act());
  }
  if(B)
  {
    B=lv_img_create(lv_scr_act());
  }
}

我对代码的运行逻辑作了进一步的详细的说明,欢迎探讨

Sunrisepeak commented 1 month ago

@sky-littlestar

重复分配不释放 导致死机 的原因, 可能是当内存不够的时候lvgl内部进行了对空指针解引用导致的程序异常引起的crash

具体可以参考: https://github.com/lvgl/lvgl/pull/6541