使用ESP32時(shí)如果懷疑存在內(nèi)存泄漏,第一步是找出程序的哪個(gè)部分正在泄漏內(nèi)存。使用xPortGetFreeHeapSize()、heap_caps_get_free_size()或相關(guān)函數(shù)來(lái)跟蹤應(yīng)用程序生命周期內(nèi)的內(nèi)存使用情況。嘗試將泄漏縮小到單個(gè)函數(shù)或函數(shù)序列,在這些函數(shù)中,可用內(nèi)存總是減少并且永遠(yuǎn)不會(huì)恢復(fù)。
一旦確定了正在泄漏的代碼:
·在項(xiàng)目配置菜單中,導(dǎo)航到Component settings -> Heap Memory Debugging -> Heap tracing,選擇Standalone選項(xiàng)。
·在程序運(yùn)行前調(diào)用heap_trace_init_standalone() 注冊(cè)一個(gè)可用于記錄內(nèi)存跟蹤的緩沖區(qū)。
·調(diào)用 heap_trace_start()開始記錄系統(tǒng)中的所有malloc/free。在你懷疑正在泄漏內(nèi)存的代碼段之前立即調(diào)用此方法。
·調(diào)用heap_trace_stop()在懷疑代碼段完成執(zhí)行后停止跟蹤。
·調(diào)用 heap_trace_dump()轉(zhuǎn)儲(chǔ)堆跟蹤的結(jié)果。
示例代碼:
#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監(jiān)視器自動(dòng)解碼PC地址到它們的源文件和行號(hào)。
第一行表示與緩沖區(qū)的總大小相比,緩沖區(qū)中有多少分配項(xiàng)。
在HEAP_TRACE_LEAKS模式下,對(duì)于每個(gè)尚未釋放的跟蹤內(nèi)存分配,打印一行:
XXbytes
為已分配的字節(jié)數(shù)@0x...
是從malloc/calloc返回的堆地址。Internal
或PSRAM
是分配內(nèi)存的一般位置。CPUx
CPU x是分配時(shí)正在運(yùn)行的CPU(0或1)。ccount0x...
是分配模式時(shí)的CCOUNT (CPU周期計(jì)數(shù))寄存器值。不同于CPU 0和CPU 1。caller0x...
給出調(diào)用malloc()/free()的調(diào)用堆棧,作為PC地址列表??梢詫⑺鼈兘獯a為源文件和行號(hào)。
可以在項(xiàng)目配置菜單中Heap Memory Debugging -> Enable heap tracing -> Heap tracing stack depth配置為每個(gè)跟蹤項(xiàng)記錄的調(diào)用堆棧的深度。每個(gè)分配最多可以記錄10個(gè)堆棧幀(默認(rèn)為2個(gè))。每增加一個(gè)堆棧幀,每個(gè)heap_trace_record_t記錄的內(nèi)存使用都會(huì)增加8個(gè)字節(jié)。
最后,打印內(nèi)存泄漏字節(jié)的總數(shù)(在運(yùn)行跟蹤時(shí)已分配但未釋放的字節(jié)),以及它所表示的總分配數(shù)。如果跟蹤緩沖區(qū)的大小不足以容納發(fā)生的所有分配,則將打印警告。如果看到此警告,應(yīng)該縮短跟蹤周期或增加跟蹤緩沖區(qū)中的記錄數(shù)量。
-
函數(shù)
+關(guān)注
關(guān)注
3文章
4346瀏覽量
62978 -
內(nèi)存泄漏
+關(guān)注
關(guān)注
0文章
39瀏覽量
9235 -
ESP32
+關(guān)注
關(guān)注
18文章
978瀏覽量
17531
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論