Understanding... Understanding "void (*state)() = NULL;"

I’m having an issue with an Arduboy sketch I had played with a long time ago that used a state machine similar to what is described here:


The issue is that when state() is called during the loop() it now seems that state loses its value when called? ie. if state is not set to a new value in whatever state function was jumped to, then the sketch hangs / crashes when that function ends??

The way this used to behave in the past is that state would retain whatever value it was last set to, until changed. But I am not sure now if expecting this behaviour was breaking the rules somehow? and at some point an update to the Arduino IDE has corrected the incorrect behaviour??

Can’t really tell more without seeing the code.

It’s probably an indirect problem.
E.g. something else is clobbering state somehow.

I had a feeling you would say that :smile: the thing is, the code had no issues last time I used it, and nothing has changed other than updates to the Arduino IDE since then… the code is a mess - it’s the text adventure game I adapted a few years back:

and would be a pain for anyone to be able to test without the same convoluted hardware setup :confused:

Inexplicably, it started working fine when I added in a Serial.println to start troubleshooting… as if just accessing state and / or having more than just the one instruction in loop() was enough to fix the problem?? Anyway, the fact that it works now is enough for me! :grinning:

The problem was happening in places where the functions were ending without explicitly setting the value of state, like at this point:

Ah, I know that text adventure game.
Someone ported it to the Pokitto and then some random parent complained about the “scream pathetically like a girl” part.

Looking at the code I can’t actually see a direct cause,
so I’m suspecting it’s one of three things:

  • A buffer overrun somewhere
  • A side effect of some optimisation
  • A side effect of the extra processing involved in an .ino file

The last possibility can be tested by putting the code in a state where the problem is present and then moving all the functions to an .h or .cpp file and calling them from the .ino.
If the problem can’t be replicated after that then it’s likely that the .ino file is the cause.

Another test is to put the code in a state where the problem is present, compile it, and then fish out the .cpp file that the Arduino IDE generates and examine it for discrepencies.

By the way, your Serial.println in loop is printing the address of the state variable, not its contents.
If the problem is optimisation related then the fact you’re taking the address of state might actually be what’s stopping the problem because taking the address of a variable forces the variable to be stored in RAM.

I can see a few ways to optimise/improve this in general.
E.g. instead of having a buffer and wasting time with strcpy_P you could just have a WriteProgmemString function.

There’s a number of other small improvements that could be made too:

  • Use bool instead of boolean
  • Use true and false instead of 1 and 0
  • Use pgm_read_ptr to read a pointer instead of pgm_read_word
  • Use uintptr_t instead of unsigned int when interpreting a pointer as an integer
  • Have a namespace GLCD instead of tacking GLCD_ on the front of functions.

I’d have a go at trying to improve the code, but I’d be flying blind,
so I’d probably end up writing something that didn’t run properly.

1 Like