使用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)推薦
ESP32硬件設(shè)計(jì)指南
ESP32硬件設(shè)計(jì)指南
![<b class='flag-5'>ESP32</b>硬件設(shè)計(jì)指南](https://file.elecfans.com/web1/M00/47/42/o4YBAFqf2lKAYnhpAACEGIpVerM705.jpg)
ESP32模組的主要特性
ESP32開發(fā)套件 ESP32-DevKitC
ESP32-WROOM-32E和ESP32-WROOM-32UE模組的區(qū)別
![<b class='flag-5'>ESP32</b>-WROOM-32E和<b class='flag-5'>ESP32</b>-WROOM-32UE模組的區(qū)別](https://file.elecfans.com/web1/M00/F2/3F/pIYBAGC18tmAYxq8AADiulFRJMg224.png)
esp32和arduino的區(qū)別,esp32能否替代arduino
ESP32-C6的特性介紹
ESP32 開發(fā)之旅② Arduino For ESP32說(shuō)明
![<b class='flag-5'>ESP32</b> 開發(fā)之旅② Arduino For <b class='flag-5'>ESP32</b>說(shuō)明](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
ESP32 SDIO 使用教程
![<b class='flag-5'>ESP32</b> SDIO 使用教程](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
ESP32系列芯片的規(guī)格
ESP32到ESP32通過(guò)Internet進(jìn)行通信
![<b class='flag-5'>ESP32</b>到<b class='flag-5'>ESP32</b>通過(guò)Internet進(jìn)行通信](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評(píng)論