刚好碰到一内存泄露问题,但不知道是谁泄露了,翻出之前调试用过的代码改了一下,很快找到泄露者了。
先是对mem.c进行改造,给每个node加入更多信息,以方便追溯。
src/mem.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 53 insertions(+), 2 deletions(-)
diff --git a/src/mem.c b/src/mem.c
index 004de01..5f83700 100644
--- a/src/mem.c
+++ b/src/mem.c @@ -112,6 +112,11 [url=home.php?mod=space&uid=1999721]@@[/url] struct heap_mem
rt_uint16_t used;
rt_size_t next, prev;
+
//代码效果参考:https://www.nbhbjx.cn/sitemap/post.html
", count, (int)mem);
", mem->magic, (mem->used)?"used":"free");
", (int)());
+
", mem->thread_name, tick - mem->tick);
", mem->file_name, mem->line);
");
- }
- rt_kprintf("mem_dump end
");
- rt_exit_critical();
+}
+#ifdef RT_USING_FINSH
+#include
+FINSH_FUNCTION_EXPORT_ALIAS(mem_dump, mem_dump, webclient multiple download test);
+#endif /* RT_USING_FINSH */
/**
- @addtogroup MM
*/
@@ -243,7 +287,7 @@ void rt_system_heap_init(void *begin_addr, void *end_addr)
- @Return pointer to allocated memory or NULL if no free memory was found.
*/
-void *rt_malloc(rt_size_t size)
+void *rt_malloc_debug(rt_size_t size, const char * file, int line)
{
rt_size_t ptr, ptr2;
struct heap_mem *mem, *mem2;
@@ -363,6 +407,13 @@ void *rt_malloc(rt_size_t size)
RT_OBJECT_HOOK_CALL(rt_malloc_hook,
(((void *)((rt_uint8_t *)mem + SIZEOF_STRUCT_MEM)), size));
-
-
mem->tick = rt_tick_get();
-
strncpy(mem->thread_name, rt_thread_self()->name, RT_NAME_MAX);
-
strncpy(mem->file_name, file, sizeof(mem->file_name) - 1);
-
mem->file_name = '';
-
mem->line = line;
-
return (rt_uint8_t *)mem + SIZEOF_STRUCT_MEM;
}
@@ -372,7 +423,7 @@ void rt_malloc(rt_size_t size)
return RT_NULL;
}
-RTM_EXPORT(rt_malloc);
+//RTM_EXPORT(rt_malloc);
/*
- This function will change the previously allocated memory block.
然后把rtthread.h中的rt_malloc指向新rt_malloc_debug
include/rtthread.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/include/rtthread.h b/include/rtthread.h
index edd207b..94830a7 100644
--- a/include/rtthread.h
+++ b/include/rtthread.h
@@ -222,7 +222,8 @@ void rt_mp_free_sethook(void (*hook)(struct rt_mempool *mp, void *block));
*/
void rt_system_heap_init(void *begin_addr, void *end_addr);
-void *rt_malloc(rt_size_t nbytes);
+void *rt_malloc_debug(rt_size_t size, const char * file, int line);
+#define rt_malloc(size) rt_malloc_debug(size, FILE, LINE)
void rt_free(void *ptr);
void *rt_realloc(void *ptr, rt_size_t nbytes);
void *rt_calloc(rt_size_t count, rt_size_t size);
然后执行测试程序,让内存多泄露一些,并让时间久一点,然后mem_dump()就能很明显找出泄露者了。
dump出来的信息格式如下
mem_dump()
mem_dump heap_ptr:0x10005AF0 heap_end:0x1000FF60
mem #0: 0x10005AF0
magic: 0000 free
mem #1: 0x100064B8
magic: 1EA0 used
thread: init, age 17779
..............
t-thread_git_forkcomponents
etlwip-1.4.1src
etifethernetif.c L:187
mem #2: 0x1000658C
magic: 1EA0 used
thread: init, age 17779
..............
t-thread_git_forkcomponentsfinshshell.c L:640
mem #3: 0x100068DC
magic: 1EA0 used
thread: init, age 17779
..............
t-thread_git_forksrcobject.c L:294
如果发现自己写的源文件名或线程名出现在上面,就可能需要仔细排查了。
不过一般泄露原因并不是申请的地方,具体还需要分析源代码。
实际排查时发现有很多app线程在kservice.c L:495申请的内存没有释放。
然后调试时等,运行到app运行就在kservice.c L:495下断点,发现有3次strdup操作,有2次内存有close函数中有释放,一个没有,泄露点顺利找到。
今天再用这个代码时,提示内存用光了。
检查发现每个item里面有128字节放文件名实在是太傻了,
把传入的 FILE 地址保存起来就OK了。
|