Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread一般讨论
关于rt_malloc的调试方法
发布于 2010-01-29 17:17:10 浏览:9733
订阅该版
系统长期运行,很担心有内存泄漏,在想办法监控,大体的思路如下: 一、包装一下malloc,例如,dbg_malloc();调用该函数,除了间接访问rt_malloc之外,还进行一次注册,注册内容包括调用者信息(例如,lr中的返回地址)和申请到的内存地址; 当然,需要提供一个buf,例如2K空间;注册信息包含其中; 二、包装free,自然,这就是反注册的步骤了,通过地址信息,清空buf中相应的条目。 假设少量malloc调用是长期租用,绝大多数的malloc是临时租用,内存泄漏点应该可以通过上述的办法得到定位。 例如一个项目占用8字节(两个地址,其实可以4字节),2K可以容纳256个注册项;注册与注销此增彼涨,相互抵消,256项目空间应该够用。但是只要有泄漏,一定会填充满,便可以得到定位。 只是有个问题,如何在一个函数中得到调用者的信息?例如,返回地址? 我想过利用编译器预定义宏,例如__LINE__,但是谁都可以看出来,还缺少文件信息;此外,完整信息难免占用空间大了些。 不知大家有什么建议?
查看更多
11
个回答
默认排序
按发布时间排序
ffxz
2010-01-30
这家伙很懒,什么也没写!
这个确实是挺麻烦的事,你也可以直接修改rt_malloc,把其中的头部加长些 是谁调用的,这点有些麻烦,Cortex-M上还不知道它的栈回朔是如何的。作为替代可以使用__FUNCTION__宏
ws_d1
2010-01-31
这家伙很懒,什么也没写!
这个宏是字串吧? 实在不行就改动rt_malloc自己添加一个参数,来个实名制。 [s:160] 我先试试看,有结果有机会再冒个泡。
bernard
2010-02-01
这家伙很懒,什么也没写!
ARMCC上,如果是ARM模式估计能够获得调用栈。Thumb-2(也就是Cortex-M3/M0)还未知 有时间再确认下,如果Thumb-2也能通过编译器扩展关键字获得调用栈的话,可以考虑在RTT中Heap管理中添加栈回溯,内存泄漏的检查。
bernard
2010-02-01
这家伙很懒,什么也没写!
Thumb-2确认能够支持,这个应该会出现在以后的RT-Thread/STM32版本中,即RT-Thread/CM3 Keil MDK/GCC 0.3.0正式版本中支持内存泄漏检查的功能(可疑泄漏点,内存分配位置)。
McuPlayer
2010-02-04
这家伙很懒,什么也没写!
比较赞同用malloc和free的宏封装的方法 在dbg版本,根据条件编译自动使用带有注册和反注册功能的的函数,rls版本则把注册功能bypass掉即可 trace的时候,使用file + line信息,考虑到存储,file最好能用ID来记录
coldfish
2010-02-05
这家伙很懒,什么也没写!
我需要动态创建一个线程,用于定时给一个消息队列发送消息。 其中DelayTime是时间间隔,Idx是一个标号。 如果收到新的命令(在CMD中),则会执行下面这断代码,先检查是否已经创建了这个线程,如果有就先删除。 然后判断命令是否符合要求,从命令中取得时间间隔和标号,重新创建线程。 ```c 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以上 手上太忙,也没空深入进去研究了,是内存回收机制?还是优先级问题?
bernard
2010-02-06
这家伙很懒,什么也没写!
可用内存近2k,但不代表这2k的内存是连续的。所以,分配不成功是有可能的。 像你这种情况,可以考虑启动一个定时器去发送消息。如果总的内存比较小,且不需要考虑动态内存,可以把系统的动态内存关闭掉,这样可用内存空间也会多一些的。
ws_d1
2010-07-07
这家伙很懒,什么也没写!
```c #include
typedef struct { unsigned short addr; //首地址(仅仅使用后两个字节) unsigned short ownr; //注册号,标识注册者 }mm_slot; //静态1K空间 mm_slot mm[256]; // 1K //地址为0,表示未被占用 #define IS_SLOT_AVAL(slot) (slot.addr == 0) //取末16位 #define USHORT_VALUE(v) ((unsigned short)(0x0000FFFF & (v))) // 统计租借者登记的次数 static int mm_owner_occur(unsigned short owner) { int i,cnt = 0; for(i = 0; i < NELEMENTS(mm); i++){ if(owner == mm[i].ownr){ cnt++; } } return cnt; } //全部清零 void mm_reset(void) { os_memset(mm, 0, sizeof(mm)); } //租用注册 void mm_reg(void* addr, unsigned short owner) { int i; for(i = 0; i < NELEMENTS(mm); i++){ if(IS_SLOT_AVAL(mm[i])){ mm[i].addr = USHORT_VALUE(((int)addr)); mm[i].ownr = owner; break; } } //空间满了,有泄漏!!! if(i >= NELEMENTS(mm)) os_printf("------------mm alert !!! ------------n"); } //归还注销 void mm_unreg(void* addr) { int i; unsigned short a = USHORT_VALUE(((int)addr)); for(i = 0; i < NELEMENTS(mm); i++){ if(a == mm[i].addr){ mm[i].addr = 0; mm[i].ownr = 0; break; } } } #define rt_list_entry(node, type, member) ((type *)((char *)(node) - (unsigned long)(&((type *)0)->member))) extern struct rt_object_information rt_object_container[]; //一个finsh命令,输出当前内存出租情况 void list_mmon(void) { int i; struct rt_thread *thread; struct rt_list_node *list, *node; os_printf("========================================n"); list = &rt_object_container[RT_Object_Class_Thread].object_list; for (node = list->next; node != list; node = node->next) { thread = rt_list_entry(node, struct rt_thread, list); os_printf("%-8s: %05u timesn", thread->name, mm_owner_occur(USHORT_VALUE(((int)thread)))); } os_printf("----------------------------------------n"); for (i = MMON_OWNER_MIN; i < MMON_OWNER_MAX; i++) { os_printf("0x%-8x: %05u timesn", i, mm_owner_occur(USHORT_VALUE(i))); } os_printf("========================================n"); } //这里就是对malloc的包装了,租借者主动提供 身份ID,作为参数 void * os_malloc_mon(unsigned long size, unsigned short owner) { void *ptr = rt_malloc(size); if(ptr){ mm_reg(ptr, owner); } return ptr; } //这里也是对malloc的包装,默认使用thread ID 作为租借身份 void * os_malloc_thread_mon(unsigned long size) { void *ptr = rt_malloc(size); if(ptr){ unsigned short owner = USHORT_VALUE(((int)rt_thread_self ())); mm_reg(ptr, owner); } return ptr; } //对free的包装 void os_free_mon(void *ptr) { if(ptr){ mm_unreg(ptr); rt_free(ptr); } } #ifdef MEM_MON_ENABLE #include "finsh.h" FINSH_FUNCTION_EXPORT(list_mmon, list_mmon) #endif ``` 对该代码感兴趣的同学,可以先参见本系列一楼,了解设计思想。 代码是其实现。使用了1K的内存,能够提供256个登记位置;能够按进程来注册,也可以指定ID。提供了一个finsh命令,能够列出哪个进程登记了多少次,或者哪个ID登记了多少次; 如果出现泄漏,看看那个登记最多的,就是光记账不还钱的主了。 按我的情况,长期运行大约可以起伏稳定在60多个登记项,占用资源不多。 工具简单,能够找出问题,我已经靠它剔除两个深藏的BUG了。 此外,该工具有点粗糙,有些效率问题,或者有竞争问题,各位当工具使用应该问题不大,用完就扔呗。 [s:154] 使用的时候请根据自己的情况 定义开关宏。希望能够对大家有用;
bernard
2010-07-07
这家伙很懒,什么也没写!
赞一个,如果能够多做些说明就更好了,内存问题是嵌入式系统开发中碰到的最大问题 [s:187]
iwillbeback008
2012-05-27
这家伙很懒,什么也没写!
也赞一个,如果能够多做些说明就更好了,内存问题是嵌入式系统开发中碰到的最大问题!!! [s:154]
撰写答案
登录
注册新账号
关注者
0
被浏览
9.7k
关于作者
ws_d1
这家伙很懒,什么也没写!
提问
6
回答
12
被采纳
0
关注TA
发私信
相关问题
1
有关动态模块加载的一篇论文
2
最近的调程序总结
3
晕掉了,这么久都不见layer2的踪影啊
4
继续K9ii的历程
5
[GUI相关] FreeType 2
6
[GUI相关]嵌入式系统中文输入法的设计
7
20081101 RT-Thread开发者聚会总结
8
嵌入式系统基础
9
linux2.4.19在at91rm9200 上的寄存器设置
10
[转]基于嵌入式Linux的通用触摸屏校准程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
单片机也能聊天?RT-Thread上跑通大语言模型
2
【RT-Thread】【ci】【scons】将ci.attachconfig.yml和scons结合使用
3
Rt-thread中OTA下载后,bootloader不搬程序
4
ulog 日志 LOG_HEX 输出时间改为本地日期时间
5
在RT-Thread Studio中构建前执行python命令
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
cubemx
PWM
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
出出啊
1518
个答案
343
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
813
个答案
177
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
149
次被采纳
本月文章贡献
出出啊
1
篇文章
5
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
3
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部