Why does filling up a large char array cause a crash? (ESP8266)

Here's the code in question:

void setup() {  
  Serial.begin(115200);
  Serial.println();
  Serial.println();

  char test[5000];
  int x;
  for(x = 0; x < sizeof(test)-1; x++){
    test[x] = 'x';
    Serial.println(x);
    yield();
  }
  Serial.println("Going to print string: ");
  test[x]='\0';
  Serial.println(test);

}

void loop() {
  // put your main code here, to run repeatedly:

}

The crash I get on my NodeMCU ESP8266, on the 828th iteration of the loop every time:

...
827
828

 ets Jan  8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x4010f000, len 3424, room 16 
tail 0
chksum 0x2e
load 0x3fff20b8, len 40, room 8 
tail 0

if I decrease the length of the array to 4000, I get a different crash, on the FIRST iteration:

0

User exception (panic/abort/assert)
--------------- CUT HERE FOR EXCEPTION DECODER ---------------

Panic core_esp8266_main.cpp:191 __yield

>>>stack>>>

ctx: sys
sp: 3fffefd0 end: 3fffffb0 offset: 0010
3fffefe0:  00000f9f 00000001 3ffee4f8 40201905  
3fffeff0:  0000009f 00000000 3ffee4f8 4020107b  
3ffff000:  feefef78 feefeffe feefeffe feefeffe  
3ffff010:  feefeffe feefeffe feefeffe feefeffe  
3ffff020:  feefeffe feefeffe feefeffe feefeffe  
3ffff030:  feefeffe feefeffe feefeffe feefeffe  
...

If I decrease the length of the array further, to 3000, nothing happens and the program runs normally as it should.

What is going on here?

Two things.

  1. Make test[] a global so you're not trying to put 5K of data on the stack.

  2. Serial.println(test); is going to try and print 5K characters w/o ever pausing for a yield(); and feeding the watchdog. You'll get away with that at 115200. You wouldn't at 9600. Something to keep in mind. (Me, I modified the core to add a yield() call to the dead spin loop in the uart_do_write_char function in cores/esp8266/uart.cpp so that I wouldn't have to intersperse Serial.print... calls with yield(); all the time.)

1 Like

Woah, making the array a global fixed it. I don't quite understand why specifically making it a global makes any difference though, as far as I understand, allocated memory is allocated memory, and I have plenty of RAM. Is it good practice to make all large arrays global? In my projects I have actually been trying to make them local to save memory once they're not needed anymore.
Also, that still doesn't explain why it triggered a Panic core_esp8266_main.cpp:191 __yield, shouldn't that only happen when you call yield() in the wrong context? I really hope you'd be able to explain this specific error, it's been haunting me this entire day.

And you're welcome.

1 Like

Oh, you mean that I haven't said thank you yet. Sorry for saying it late, and thank you. Even if I won't get answers to those questions even knowing how to work around the problem is a relief.

That device also has a memory manager and you may be overrunning one of it's limits.

Hi, thanks for the response, you mean a dedicated memory manager that would set limits on the stack array sizes? I haven't been able to find any results on google for this, could you point me to some please?

Read the data sheets for your processor! The memory manager is part of the microprocessor!

On "small" microcontrollers like the AVR, the stack is usually initialized to start at the top of memory and grow downward, and can essentially use ALL of the RAM for stack (until it silently collides with RAM being used for something else, at which point you get all sorts of problems.)

On the "bigger" microcontrollers, particularly those running a networking stack (like the ESPs), the "sketch process" is more likely to be allocated a fixed-sized stack that cannot grow as needed (and it looks like it is somewhat protected here, since you get an actual crash rather than just weird behavior.)

Thank you, that makes sense. Interesting it triggered the watchdog and panic, but I guess I'm in undefined behaviour territory when I get over that limit. Do you happen to know if it's the same limit for every sketch? Or does it get change somehow with the amount of variables? It's weird I've never encountered any mention of the limit on the internet, it's a pretty dangerous thing.

I've looked it up, max stack size is 4096 for every sketch. Well, from now on I won't be using the stack for large variables. Thanks a lot guys, I've learned a lot.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.