嵌入式技术william hill官网
直播中

ss

7年用户 8762经验值
擅长:电源/新能源 制造/封装 RF/无线
私信 关注
[问答]

怎样去解决RT-Thread系统长期运行导致内存泄漏的问题呢

系统长期运行,很担心有内存泄漏,在想办法监控,大体的思路如下:
一、包装一下malloc,例如,dbg_malloc();调用该函数,除了间接访问rt_malloc之外,还进行一次注册,注册内容包括调用者信息(例如,lr中的返回地址)和申请到的内存地址;
当然,需要提供一个buf,例如2K空间;注册信息包含其中;
二、包装free,自然,这就是反注册的步骤了,通过地址信息,清空buf中相应的条目。
假设少量malloc调用是长期租用,绝大多数的malloc是临时租用,内存泄漏点应该可以通过上述的办法得到定位。
例如一个项目占用8字节(两个地址,其实可以4字节),2K可以容纳256个注册项;注册与注销此增彼涨,相互抵消,256项目空间应该够用。但是只要有泄漏,一定会填充满,便可以得到定位。
只是有个问题,如何在一个函数中得到调用者的信息?例如,返回地址?
我想过利用编译器预定义宏,例如__LINE__,但是谁都可以看出来,还缺少文件信息;此外,完整信息难免占用空间大了些。
不知大家有什么建议?

回帖(5)

ss

2022-3-17 09:41:31
这个确实是挺麻烦的事,你也可以直接修改rt_malloc,把其中的头部加长些

是谁调用的,这点有些麻烦,Cortex-M上还不知道它的栈回朔是如何的。作为替代可以使用__FUNCTION__宏。
举报

ss

2022-3-17 09:41:53
这个宏是字串吧?
实在不行就改动rt_malloc自己添加一个参数,来个实名制。

我先试试看,有结果有机会再冒个泡。
举报

ss

2022-3-17 09:42:21
比较赞同用malloc和free的宏封装的方法
在dbg版本,根据条件编译自动使用带有注册和反注册功能的的函数,rls版本则把注册功能bypass掉即可
trace的时候,使用file + line信息,考虑到存储,file最好能用ID来记录。
举报

ss

2022-3-17 09:43:04
我需要动态创建一个线程,用于定时给一个消息队列发送消息。

其中DelayTime是时间间隔,Idx是一个标号。

如果收到新的命令(在CMD中),则会执行下面这断代码,先检查是否已经创建了这个线程,如果有就先删除。

然后判断命令是否符合要求,从命令中取得时间间隔和标号,重新创建线程。

            if (ctt_thread != RT_NULL)

                rt_thread_delete(ctt_thread);

            if (rt_strlen(CMD+j)>0)

            {

                SSS.DelayTime=atoi(CMD+j);

                SSS.Idx=Curdx;

                ctt_thread = rt_thread_create("CTT",rt_thread_entry_ctt, RT_NULL,

                                               256,24,100);

                if (ctt_thread != RT_NULL)

                    rt_thread_startup(ctt_thread);

            }

现在奇怪的是,在其他线程都是静态线程和静态变量时,ctt_thread = rt_thread_create()有时能成功,有时不能成功,跟踪进去,发现是 stack_start = (void*)rt_malloc(stack_size);

有时能申请成功,有时申请不成功,这是怎么回事?而且256也不算大,我的可用内存都在2K以上

手上太忙,也没空深入进去研究了,是内存回收机制?还是优先级问题?
举报

ss

2022-3-17 09:43:23
可用内存近2k,但不代表这2k的内存是连续的。所以,分配不成功是有可能的。

像你这种情况,可以考虑启动一个定时器去发送消息。如果总的内存比较小,且不需要考虑动态内存,可以把系统的动态内存关闭掉,这样可用内存空间也会多一些的。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分