I like how - always, without fail - whenever a topic related to robustness or integrity is broached, everyone always jumps straight in to the deep end and assumes you're doing something safety- or life-critical, and starts talking about triple-redundancy, memory-scrubbing, ECC, radiation-hardening, ISO safety standards, type- and memory-safe languages, static analysis, CRCs, etc, etc, etc.
Yes, often the XY Problem is manifest, and generalising is best rather than sticking to the specific topic at hand so that the OP is informed about wider things that they may need to consider. But sheesh, guys, give it a break sometimes...
So let me just clarify:
- No, I'm not doing anything safety- or life-critical.
- No, I'm not in need of complying with any regulatory framework.
- No, I'm extremely unlikely to get sued if my system fails.
- No, I'm not sending anything into space, or controlling a nuclear reactor, X-rays, lasers, etc.
With that said, yes, I appreciate there are a whole lot of other things that can go wrong, and that a single state variable in memory is a drop in the ocean, all things considered. It just that it occurred to me the other day that I'm writing some code where if the internal state gets corrupted, annoying things may happen, and I wondered "how can I make this better?". Not ideal, not perfection, just a little bit better. And so I think aiding the integrity of the keystone of the execution of my system is not wholly futile.
I think I'm not going to go overkill, and will just go with keeping a second inverse copy of the state variable.
typedef enum {
STATE_FOO = 1,
STATE_BAR = 2,
/* etc... */
} state_enum_t;
typedef struct {
state_enum_t state;
state_enum_t inverse;
} state_t;
static volatile state_t state;
#define state_current() (state.state)
#define state_change(s) do { state.state = (s); state.inverse = ~(s); } while(0)
#define state_is_valid() ((state.state ^ state.inverse) == -1)
The state will only be changed using the
state_change() macro, and every time through the main loop the state will be verified with
state_is_valid().