OC
OceanRemote
Low-code IoT platform
Back to Troubleshooting Hub

ESP8266 Low Memory Crash

Fix heap fragmentation, memory leaks, and insufficient RAM issues causing random reboots

10 min read

Symptoms

  • Device reboots randomly every few minutes or hours
  • Serial monitor shows: "Fatal exception 28" or "wdt reset"
  • Out-of-memory error messages before reboot
  • Crashes worsen over time
  • Device resets when performing normal operations

Common Causes

  1. Memory leaks: malloc() without paired free(), string concatenation without cleanup
  2. Heap fragmentation: Many small allocs/deallocs create unusable fragments
  3. Stack overflow: Large local arrays/buffers consume stack space
  4. Inefficient WiFi code: WiFi connections without yield() cause WDT timeout
  5. String concatenation: String + String + String causes multiple allocations
  6. Missing resource cleanup: HTTP clients, WiFi scans, file handles not closed

Memory Reference Table

Memory Type Size Used For
Internal RAM160 KBHeap + Stack
Stack~4-8 KBLocal variables, call frames
Heap~150 KBmalloc(), String objects
Flash VariesFile storage, EEPROM

Step-by-Step Fixes

1. Monitor Heap Memory

Track free memory to identify when crashes occur:

void printMemoryStats() {
  uint32_t free = ESP.getFreeHeap();
  uint16_t maxFree = ESP.getMaxFreeBlockSize();
  
  Serial.print; Serial.print; Serial.println;
  Serial.print; Serial.print; Serial.println;
  Serial.print;
  Serial.println) / free);
  Serial.println();
}

void loop() {
  printMemoryStats();
  delay;
}

2. Find Memory Leaks

Always pair malloc() with free():

//  WRONG - Memory leak
void fetchData() {
  char* buffer = (char*)malloc;
  // ... use buffer ...
  // Missing free - LEAK!
}

//  CORRECT - Proper cleanup
void fetchData() {
  char* buffer = (char*)malloc;
  // ... use buffer ...
  free;  // Restore memory
}

3. Avoid String Concatenation

Use StringBuilder patterns instead:

//  WRONG - Multiple allocations
String msg = "Device: " + deviceID + " Status: " + status + " Value: " + value;

//  CORRECT - Single buffer
char buffer[256];
snprintf, "Device: %s Status: %s Value: %d", 
         deviceID, status, value);
String msg = buffer;

4. Use yield() in Loops

Prevent watchdog timeout that causes resets:

void connectWiFi() {
  WiFi.begin;
  
  int attempts = 0;
  while  != WL_CONNECTED && attempts < 20) {
    delay;
    yield();  // Feed watchdog, allow background tasks
    attempts++;
  }
}

5. Close WiFi Scans Properly

WiFi.scanNetworks() allocates large buffers:

void scanNetworks() {
  int n = WiFi.scanNetworks();
  
  for  {
    Serial.println);
  }
  
  WiFi.scanDelete();  // FREE memory from scan
}

6. Optimize SPIFFS Allocation

Reduce SPIFFS partition to give more RAM to heap:

// Arduino IDE: Tools  Flash Size  Select smaller SPIFFS
// Example: 2MB   ~150KB heap
// Check your partition size:
FSInfo fsInfo;
SPIFFS.info;
Serial.print; Serial.println;

Prevention Tips

  • Always pair malloc() with free() - never leave memory dangling
  • Avoid concatenating Strings; use snprintf() or StringBuilder patterns
  • Call yield() in all loops to feed the watchdog timer
  • Use WiFi.scanDelete() after WiFi.scanNetworks() to free memory

Related Issues

FAQ

Q: How much free memory do I need to operate safely?

A: Keep at least 20-30KB free. Below 10KB, crashes become likely. Monitor with ESP.getFreeHeap().

Q: What causes "Fatal exception 28"?

A: LoadProhibited means accessing invalid memory address .

Q: Can I use PSRAM on ESP8266?

A: No. Only ESP32 supports external PSRAM. ESP8266 is limited to 160KB internal RAM.

Still having issues? Contact Support or return to the Troubleshooting Hub.