The problem with that theory is that the screen buffer is a static member variable, so it should be zero-initialised before setup()
even runs.
I think what’s actually going on is that the memory in the screen itself still holds whatever was in it before the reboot because display()
was never called.
So to track down where the problem lies I did some testing by interleaving Serial.println(__COUNTER__)
througout setup()
, like so:
void setup()
{
while(!Serial) {}
Class::arduboy.begin();
Class::arduboy.setFrameRate(15);
Serial.println(__COUNTER__);
xcur = Class::exemplar->make("C20");
Serial.println(__COUNTER__);
ycur = Class::exemplar->make("C7");
Serial.println(__COUNTER__);
scene = Class::exemplar->make("S");
Serial.println(__COUNTER__);
scene->atPut(Class::Directive::X, xcur);
Serial.println(__COUNTER__);
scene->atPut(Class::Directive::Y, ycur);
Serial.println(__COUNTER__);
scene->atGet(Class::Directive::Build);
Serial.println(__COUNTER__);
delete xcur;
Serial.println(__COUNTER__);
delete ycur;
Serial.println(__COUNTER__);
xcur = Class::exemplar->make("C5");
Serial.println(__COUNTER__);
ycur = Class::exemplar->make("C5");
Serial.println(__COUNTER__);
scene->atPut(Class::Directive::X, xcur);
Serial.println(__COUNTER__);
scene->atPut(Class::Directive::Y, ycur);
Serial.println(__COUNTER__);
player = Class::exemplar->make("\x01Player");
Serial.println(__COUNTER__);
scene->atPut(Class::Directive::Character, player);
Serial.println(__COUNTER__);
}
Note: __COUNTER__
is a compiler-specific macro,
please do not rely on it for any serious code.
I’m only using it here for the sake of quickness.
The output was:
0
1
2
3
4
5
Which puts the sticking point at:
scene->atGet(Class::Directive::Build);
So I threw in a few more serial prints…
case Class::Directive::Build: //build the scene and bounds
_xsize = ::atoi(_xcoord->toStr());
Serial.println('A');
_ysize = ::atoi(_ycoord->toStr());
Serial.println('B');
_characters = new Class*[_xsize * _ysize] {};
Serial.println('C');
return this;
break;
(By the way, that break
is unreachable code,
the return
will exit the function before the break
is reached.)
This time I get:
0
1
2
3
4
5
A
B
So, long story short, new
is getting stuck.
Chances are you’re trying to allocate too much memory so the Arduboy is just getting stuck.
This is precisely why we say don’t use dynamic memory allocation on Arduboy.
You don’t get a compiler error, you don’t get any kind of warning,
your program just seizes up at runtime and you’re left scratching your head.
So to answer your question:
Your problem isn’t heap fragmentation.
The heap isn’t even living long enough to become fragmented because you’re not deleting anything,
you’re simply trying to allocate more member than the Arduboy can handle.
Honestly though, I dug through your code and I’m having a hard time trying to figure out what the values of _xsize
and _ysize
actually are.
To be very blunt, I think you seriously need to rethink how your code is designed.
Using new
and delete
on an embedded system with so little RAM is a bad idea.
Trying to pass integers around as strings and using atoi
to parse them back out is also a bad idea.
I can’t help but wonder if perhaps you’re used to using a language like Python or JavaScript so you’re perhaps having a hard time because you’re used to being able to use as much memory as you want, or using odd design patterns that only work in certain environments.