ESP32 running out of memory

I am writing a code that runs fine on my pc buts runs out of memory.
There is a specific part of the code where the esp says

Guru Meditation Error: Core 1 panic'ed (Unhandled debug exception)
Debug exception reason: Stack canary watchpoint triggered (loopTask)
Core 1 register dump:
PC : 0x400d3254 PS : 0x00060636 A0 : 0x800d3824 A1 : 0x3ffb0030
A2 : 0x0000000e A3 : 0x3ffcc4cc A4 : 0xfffffe77 A5 : 0x00000080
A6 : 0x00000000 A7 : 0x00000001 A8 : 0x3ffc1c24 A9 : 0x00000008
A10 : 0xfffffce1 A11 : 0x00000002 A12 : 0x00000002 A13 : 0x00000353
A14 : 0x0000000a A15 : 0x3ffb08d0 SAR : 0x00000011 EXCCAUSE: 0x00000001
EXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xfffffff8

ELF file SHA256: 0000000000000000

Backtrace: 0x400d3254:0x3ffb0030 0x400d3821:0x3ffb0170 0x400d3821:0x3ffb02b0 0x400d3821:0x3ffb03f0 0x400d3821:0x3ffb0530 0x400d3821:0x3ffb0670 0x400d3821:0x3ffb07b0 0x400d3821:0x3ffb08f0 0x400d3821:0x3ffb0a30 0x400d3821:0x3ffb0b70 0x400d3821:0x3ffb0cb0 0x400d3821:0x3ffb0df0 0x400d3821:0x3ffb0f30 0x400d3821:0x3ffb1070 0x400d3821:0x3ffb11b0 0x400d3821:0x3ffb12f0 0x400d3821:0x3ffb1430 0x400d3821:0x3ffb1570 0x400d3821:0x3ffb16b0 0x400d3821:0x3ffb17f0 0x400d3821:0x3ffb1930 0x400d3821:0x3ffb1a70 0x400d3821:0x3ffb1bb0 0x400d493c:0x3ffb1cf0 0x400d683b:0x3ffb1e30 0x400d71a4:0x3ffb1ef0 0x400e352d:0x3ffb1fb0 0x4008a1fe:0x3ffb1fd0

Rebooting...

The code I am trying to run is this one

void refillSet(uint8_t i, uint8_t j, uint16_t n)
{
  //log("yo");

  if (flood[i][j] == 512 && ((i == box / 2 || i == box / 2 - 1) && (j == box / 2 || j == box / 2 - 1)))
  {
    n = 0;
  }
  else if (flood[i][j] <= n)
    return;

  flood[i][j] = n;

  if ((global[i][j] | nwN) != TW && flood[i - 1][j] > n)
    refillSet((i - 1), j, (n + 1));

  if ((global[i][j] | nwE) != TW && flood[i][j + 1] > n)
    refillSet(i, (j + 1), (n + 1));

  if ((global[i][j] | nwS) != TW && flood[i + 1][j] > n)
    refillSet((i + 1), j, (n + 1));

  if ((global[i][j] | nwW) != TW && flood[i][j - 1] > n)
    refillSet(i, (j - 1), (n + 1));
}

Her the maximum value of i and j is 16 and minimum is 0.
And global in uint8_t global[16][16]
and flood is uint16_t flood[16][16]

What am I doing wrong?

At least two things:

  1. You didn't post your complete code.

  2. You didn't post the results of running the dump message through the ESP Exception Decoder.

1 Like
const uint8_t box=16;

uint16_t flood[box][box];
uint8_t global[box][box];


void setup() {
  // put your setup code here, to run once:
Serial.begin(19200);
}

void loop() {
  // put your main code here, to run repeatedly:
refillSetup();
refillSet(0,0,0);
}

void globalSetup()
{

  for (uint8_t i = 0; i < box; i++)
  {
    for (uint8_t j = 0; j < box; j++)
    {
      global[i][j] = 0;

      if (i == 0)
        global[i][j] = 8;

      if (j == box - 1)
        global[i][j] = 4;

      if (i == box - 1)
        global[i][j] = 2;

      if (j == 0)
        global[i][j] = 1;
    }
  }
  // marks the corner boxes
  global[0][0] = 9;
  global[0][box - 1] = 12;
  global[box - 1][0] = 3;
  global[box - 1][box - 1] = 6;
}

void refillSetup()
{
  for (uint8_t i = 0; i < box; i++)
  {
    for (uint8_t j = 0; j < box; j++)
      flood[i][j] = (512);
  }
}

void refillSet(uint8_t i, uint8_t j, uint16_t n)
{
  //log("yo");
  //Serial.println("yo");

  if (flood[i][j] == 512 && ((i == box / 2 || i == box / 2 - 1) && (j == box / 2 || j == box / 2 - 1)))
  {
    n = 0;
  }
  else if (flood[i][j] <= n)
    return;

  flood[i][j] = n;

  if ((global[i][j] | 7) != 15 && flood[i - 1][j] > n)
    refillSet((i - 1), j, (n + 1));

  if ((global[i][j] | 11) != 15 && flood[i][j + 1] > n)
    refillSet(i, (j + 1), (n + 1));

  if ((global[i][j] | 13) != 15 && flood[i + 1][j] > n)
    refillSet((i + 1), j, (n + 1));

  if ((global[i][j] | 15) != 15 && flood[i][j - 1] > n)
    refillSet(i, (j - 1), (n + 1));
}

Recursion?
Uh-oh.

2 Likes

But there is only 4 bytes per recursion for a maximum of 1024 times. This shouldn't outrun a ESP32?

I am running IDE 2.0 so the exception decoder does not work

Then install IDE 1.8.19 and run it there.

1 Like

Yeah, i am doing that right now, my internet is just a little slow

Recursion is great for reasoning about an algorithm, but unless it's a simple tail recursion, you should not actually implement it like that, especially on a microcontroller. Deep recursion causes stack overflows, so you should use a loop instead, possibly keeping your own “stack” if necessary.

I tried to do that, but that makes the code run slower, so i am not sure what to do

Working code >> code that crashes very quickly. You can always optimize later if necessary.

Thanks for the advice, will try again

The stack decoder

PC: 0x40083779
EXCVADDR: 0x00000000

Decoding stack results
0x400d0fce: Print::write(char const*) at C:\Users\Anurag Gupta\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\cores\esp32/Print.h line 67
0x400d0fe1: Print::println() at C:\Users\Anurag Gupta\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\cores\esp32\Print.cpp line 89
0x400d0ffd: Print::println(char const*) at C:\Users\Anurag Gupta\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\cores\esp32\Print.cpp line 196
0x400d0c34: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 59
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74
0x400d0cd2: refillSet(unsigned char, unsigned char, unsigned short) at C:\Users\Anurag Gupta\Documents\Arduino\Test-ESP32/Test-ESP32.ino line 74

Certainly looks like recursion is the problem.

Thanks, I am trying to go for the loop.

So i kind of had a small question, suppose i do

while(isRunning)
{
    uint8_t x=0;
    x++;
}

Suppose if the loop runs 500 times, will only 1 x be created or 500 x s. I kind of think the x will be deleted and regenerated again, but just asking for confirmation.

Since you're defining 'x' as a local variable within the 'while' loop, it would conceptually be created then destroyed on the stack on every pass through the loop. But, the compiler is likely to see that the entire loop serves no purpose and will completely remove it.

Oh, so if i create x outside the loop like this

uint8_t x=0;
while(isRunning)
{
    x++;
    stuff(x);
}

will this be better than assigning inside the loop?

How will 'isRunning' be set to false so that execution is not stuck in the loop forever?

1 Like

stuff() does something to stop that, when a condition is reached. But I don't understand how this information is useful to answer the above question.