Automated Reptile Control System(webserver, Data Logging, RTC and much more)

Check in the playground for memory usage. There are a couple of routines there that can tell you how much you have left at any given time. I use them extensively to keep away from running out of memory. You can put them in temporarily to measure what you have left and isolate a problem area then fix whatever is needed.

In a couple of hard cases, I put them in the loop() and automatically rebooted the board to clean things out when free memory reached a low number. This was a stop gap measure I used while I tried to figure out what the heck was going on. These days, I try desperately to avoid using Strings and use the old reliable strcat, strcmp, etc. instead.

Something like:

#include <avr/pgmspace.h>

void showMem(){
  uint8_t * heapptr, * stackptr;
  
  strcpy_P(Dbuf,PSTR("Mem = "));
  Serial.print(Dbuf);
  stackptr = (uint8_t *)malloc(4);   // use stackptr temporarily
  heapptr = stackptr;                // save value of heap pointer
  free(stackptr);                    // free up the memory again (sets stackptr to 0)
  stackptr =  (uint8_t *)(SP);       // save value of stack pointer
  Serial.println(stackptr - heapptr);
}

// and then sprinkle these around to get a feel for what is going on

    showMem();

Or maybe you would prefer:

#include <MemoryFree.h>

void showMem(){
  strcpy_P(Dbuf,PSTR("Mem = "));
  Serial.print(Dbuf);
  Serial.println(freeMemory());
}

// and then, as above, I sprinkle these around to see what is happening

showMem();

I use both in different applications. Don't have a preference either way.