ESP32内存泄露

电子说

1.3w人已加入

描述

使用ESP32时如果怀疑存在内存泄漏,第一步是找出程序的哪个部分正在泄漏内存。使用xPortGetFreeHeapSize()、heap_caps_get_free_size()或相关函数来跟踪应用程序生命周期内的内存使用情况。尝试将泄漏缩小到单个函数或函数序列,在这些函数中,可用内存总是减少并且永远不会恢复。

一旦确定了正在泄漏的代码:

·在项目配置菜单中,导航到Component settings -> Heap Memory Debugging -> Heap tracing,选择Standalone选项。

内存泄漏

·在程序运行前调用heap_trace_init_standalone() 注册一个可用于记录内存跟踪的缓冲区。

·调用 heap_trace_start()开始记录系统中的所有malloc/free。在你怀疑正在泄漏内存的代码段之前立即调用此方法。

·调用heap_trace_stop()在怀疑代码段完成执行后停止跟踪。

·调用 heap_trace_dump()转储堆跟踪的结果。

示例代码:

#include "esp_heap_trace.h"


#define NUM_RECORDS 100
static heap_trace_record_t trace_record[NUM_RECORDS]; // This buffer must be in internal RAM


...


void app_main()
{
    ...
    ESP_ERROR_CHECK( heap_trace_init_standalone(trace_record, NUM_RECORDS) );
    ...
}


void some_function()
{
    ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );


    do_something_you_suspect_is_leaking();


    ESP_ERROR_CHECK( heap_trace_stop() );
    heap_trace_dump();
    ...
}

堆跟踪的输出大概这样:

2 allocations trace (100 entry buffer)
32 bytes (@ 0x3ffaf214) allocated CPU 0 ccount 0x2e9b7384 caller 0x400d276d:0x400d27c1
0x400d276d: leak_some_memory at /path/to/idf/examples/get-started/blink/main/./blink.c:27


0x400d27c1: blink_task at /path/to/idf/examples/get-started/blink/main/./blink.c:52


8 bytes (@ 0x3ffaf804) allocated CPU 0 ccount 0x2e9b79c0 caller 0x400d2776:0x400d27c1
0x400d2776: leak_some_memory at /path/to/idf/examples/get-started/blink/main/./blink.c:29


0x400d27c1: blink_task at /path/to/idf/examples/get-started/blink/main/./blink.c:52


40 bytes 'leaked' in trace (2 allocations)
total allocations 2 total frees 0

上面的示例输出是使用IDF监视器自动解码PC地址到它们的源文件和行号。

第一行表示与缓冲区的总大小相比,缓冲区中有多少分配项。

在HEAP_TRACE_LEAKS模式下,对于每个尚未释放的跟踪内存分配,打印一行:

  • XXbytes 为已分配的字节数
  • @0x... 是从malloc/calloc返回的堆地址。
  • InternalPSRAM 是分配内存的一般位置。
  • CPUx CPU x是分配时正在运行的CPU(0或1)。
  • ccount0x... 是分配模式时的CCOUNT (CPU周期计数)寄存器值。不同于CPU 0和CPU 1。
  • caller0x... 给出调用malloc()/free()的调用堆栈,作为PC地址列表。可以将它们解码为源文件和行号。

可以在项目配置菜单中Heap Memory Debugging -> Enable heap tracing -> Heap tracing stack depth配置为每个跟踪项记录的调用堆栈的深度。每个分配最多可以记录10个堆栈帧(默认为2个)。每增加一个堆栈帧,每个heap_trace_record_t记录的内存使用都会增加8个字节。

最后,打印内存泄漏字节的总数(在运行跟踪时已分配但未释放的字节),以及它所表示的总分配数。如果跟踪缓冲区的大小不足以容纳发生的所有分配,则将打印警告。如果看到此警告,应该缩短跟踪周期或增加跟踪缓冲区中的记录数量。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分