使用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返回的堆地址。Internal
或PSRAM
是分配內存的一般位置。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個字節。
最后,打印內存泄漏字節的總數(在運行跟蹤時已分配但未釋放的字節),以及它所表示的總分配數。如果跟蹤緩沖區的大小不足以容納發生的所有分配,則將打印警告。如果看到此警告,應該縮短跟蹤周期或增加跟蹤緩沖區中的記錄數量。
-
函數
+關注
關注
3文章
4338瀏覽量
62739 -
內存泄漏
+關注
關注
0文章
39瀏覽量
9226 -
ESP32
+關注
關注
18文章
971瀏覽量
17361
發布評論請先 登錄
相關推薦
評論