Detecting and Fixing FreeRTOS Memory Leaks on ESP32
What causes this
Memory leaks in FreeRTOS on ESP32 often stem from improper task or queue management, failure to free dynamically allocated memory, or incorrect stack size allocation. In FreeRTOS, when a task is created using xTaskCreate, memory is allocated for its stack. If the task is deleted without freeing this memory using vTaskDelete and ensuring the stack memory is released, a memory leak occurs. The ESP32's heap, managed by the heap_caps_malloc function, can exhibit increasing usage over time if leaks are present. Registers like ESP32_HEAP_START and ESP32_HEAP_END can help monitor memory usage, and errors may manifest as ESP_ERR_NO_MEM during allocation attempts.
Minimal reproduction
To reproduce a memory leak in FreeRTOS on ESP32, consider the following code snippet:
```c
#include
#include
void LeakyTask(void *pvParameters) {
while(1) {
char *leak = pvPortMalloc(100);
vTaskDelay(pdMS_TO_TICKS(1000));
// vPortFree(leak); // Intentional omission to simulate leak
}
}
void app_main() {
xTaskCreate(LeakyTask, "LeakyTask", 2048, NULL, 1, NULL);
}
```
Expected serial output after running for some time:
```
E (50000) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (50000) task_wdt: - LeakyTask (CPU 0)
E (50000) heap_alloc_caps: malloc failed, heap is exhausted: ESP_ERR_NO_MEM
```
The fix
To fix the memory leak, ensure that all dynamically allocated memory is freed after use. Here’s the corrected version of the task:
Before:
```c
char *leak = pvPortMalloc(100);
vTaskDelay(pdMS_TO_TICKS(1000));
// vPortFree(leak); // Intentional omission to simulate leak
```
After:
```c
char *leak = pvPortMalloc(100);
vTaskDelay(pdMS_TO_TICKS(1000));
vPortFree(leak);
```
Also, monitor heap usage using FreeRTOS heap functions:
```c
size_t freeHeap = xPortGetFreeHeapSize();
ESP_LOGI("Heap", "Free heap size: %u", freeHeap);
```
How SerialDoctor catches this
SerialDoctor connects to your ESP32 via Web Serial, reading the serial output to quickly identify memory leaks. By analyzing the output, SerialDoctor can pinpoint errors like ESP_ERR_NO_MEM and suggest likely causes, such as unfreed memory allocations, all within 3 seconds. Visit [serialdoctor.com](https://serialdoctor.com) to see it in action.
Quick checklist
- [ ] Ensure every
pvPortMallochas a correspondingvPortFree. - [ ] Regularly monitor heap usage with
xPortGetFreeHeapSize. - [ ] Allocate sufficient stack size for tasks to avoid overflow.
- [ ] Use task watchdogs to catch tasks that hang due to memory issues.
- [ ] Employ tools like SerialDoctor for quick diagnosis of serial output.
Seeing this crash on your board right now?
Connect it to SerialDoctor and get a root cause + code fix in under 3 seconds.
Try SerialDoctor free →