Spot the bug

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;
  }
    sInit:

Where are the case statements?

What type is State? What types are sReset, etc.?

Debug.println();

How is this defined?

PaulS:
Where are the case statements?

The award goes to PaulS! Well done!

With or without "case" the code compiles. Without "case" the code obviously does not function correctly.

I assume the compiler treats them as labels. Which means switch can contain irrelevant code and be empty.

Oh, the caveats of working in Pascal then C++!

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).

-Wall would have help catch that... :wink:

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.

--- bill

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.

bperrybap:
-Wall would have help catch that... :wink:

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 am surprised that nobody complained that you did not post your whole program :slight_smile:

From their questions it is safe to assume both @PaulS and @LarryD were on that path.

The source code for the project is about 420K (core+sketch). I don't think I'll be posting that for a missing "case" bug. :wink:

UKHeliBob:
I am surprised that nobody complained that you did not post your whole program :slight_smile:

At least he used code tags. :stuck_out_tongue:

At least he used code tags. :stuck_out_tongue:

They were added by a moderator :wink:

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).

@Nick Gammon

Got this in Tips Traps and Style Guide?

.

Recall that default is simply a label, too.

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)".

LarryD:
@Nick Gammon

Got this in Tips Traps and Style Guide?

It's there now. :slight_smile:

Thanks to Coding Badly for the nice example. :stuck_out_tongue:

Does rewriting like this help...

Not really.

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.