The following code contains a fatal run-time flaw. Can you find it? (In context, the code compiles without error.)
switch ( State )
{
sInit:
Debug.println( F( "sI" ) );
// fix: Check Vcc. Scream and die if it is out of range.
State = sLoad0_Enter;
break;
sLoad0_Enter:
// SayHello.turnOn();
// Give the human two minutes to load the pan
Debug.println( F( "120s" ) );
GenericTimer.start( 120 );
State = sLoad0;
break;
sLoad0:
if ( Action.clicked() )
{
State = sPowerOff; // fix: Time to run!
}
else if ( GenericTimer.finished() )
{
Debug.println( F( "PoOff" ) );
State = sPowerOff;
}
break;
sPowerOff:
//KitchenTimer.cancel();
GenericTimer.cancel();
//AlertDone.turnOff();
//AttentionDone.turnOff();
//AchtungDone.turnOff();
//SayGoodbye.turnOn();
State = sFinishTuning;
break;
sFinishTuning:
Debug.println();
State = sReset;
break;
}
Yes they are treated as labels. The last case however cannot be empty, the same as labels at the end of a function (there must be at least one statement/semicolon).
Too bad the IDE now disables all warnings all the time, including when verbose mode is selected.
But you can fix that and add -Wall into the platform file. (I do)
I prefer to use -Werror but that can't be used with Arduino since there are issues in the core code and libraries that the IDE ships with.
I think this part of the Standard covers that behaviour:
When the switch statement is executed, its condition is evaluated and compared with each case constant. If one of the case constants is equal to the value of the condition, control is passed to the statement following the matched case label. If no case constant matches the condition, and if there is a default label, control passes to the statement labeled by the default label. If no case matches and if there is no default then none of the statements in the switch is executed.
Since there are no case constants, then control is not passed to any part of the switch statement.
Well, the warnings are a tiny bit better than nothing...
CT1.ino: In function 'void loop()':
CT1.ino:84:5: warning: label 'sInit' defined but not used [-Wunused-label]
CT1.ino:89:5: warning: label 'sLoad0_Enter' defined but not used [-Wunused-label]
CT1.ino:96:5: warning: label 'sLoad0' defined but not used [-Wunused-label]
CT1.ino:107:5: warning: label 'sPowerOff_Enter' defined but not used [-Wunused-label]
CT1.ino:120:5: warning: label 'sPowerOff' defined but not used [-Wunused-label]
But, they are difficult to spot in the noise.
But you can fix that and add -Wall into the platform file. (I do)
I've been building with the default (no -w or -W option) which gives a nice balance. While developing I find -Wall produces too much noise.
I prefer to use -Werror but that can't be used with Arduino since there are issues in the core code and libraries that the IDE ships with.
I have a few bits of code that would be difficult to eliminate all warnings (unused variable). It is just not worth the complication. So no -Werror for me.
The problem is not just the Arduino core. For example, "BIN", a fairly common name to find in user code, is a Libc macro for some ATtiny processors. Nearly every project I have includes a few warnings because of the lack of namespace management. So no -Werror for me.
The problem is not just the Arduino core. If nuisance warnings (like unused variable) had been errors the community would be much much smaller. The last thing someone new to C++ wants to deal with are confusing and mostly irrelevant "errors".
Anyway, thanks for the -Wall suggestion. I'll turn it on from time-to-time.
Yup. Exactly what was happening. None of the code was running. Which made it easy to tell something was wrong.
I was just asking about the missing case statements, because a switch statement that did nothing appeared to be useless. I don't see how that caused "a fatal run-time flaw". Having nothing happen when you expect something to happen should not be fatal.
I guess I'm missing something (besides the rest of the code).
You might want a label and goto in a switch to provide cleanup code for some cases.
Is this where we are supposed to mention Duff's Device?
C's default fall-through in case statements has long been one of its most controversial features; Duff observed that "This code forms some sort of argument in that debate, but I'm not sure whether it's for or against."[1]
I don't see how that caused "a fatal run-time flaw". Having nothing happen when you expect something to happen should not be fatal.
Was I a bit too over dramatic? (I was certainly terse.)
I guess I'm missing something (besides the rest of the code).
Does rewriting like this help...
The following code snippet contains a mistake leading to failure at run-time. Can you find the mistake? (With the rest of the code everything compiles without error.)
The goal would be to determine what the failure is (does nothing when something was expected) and why the failure occurs (forgot "case)".
The following code snippet contains a mistake leading to failure at run-time.
If "failure" means code not executing the way the programmer expects, that's one thing. But, that sounds like an attempt to blame the code or the compiler, when the "fault" lies elsewhere.
Had you said "this code does not do what I expect", without even looking at it I'd ask you what it does (nothing) and what you expect (your answer here). Then, I'd ask (after looking at your code) how you could expect that behavior, given that no cases were defined.
I guess we got there, in the beginning, though, rather than in the end, so it doesn't really matter. It just helps to understand what all the terms mean.