this is from the french forum discussion - brought by @bidouilleelec and worth additional eyeballs looking at it for what is either a super aggressive supposedly “dead loop” / “dead code” removal optimization or a compiler bug.
(tested with 1.8.5 / avr-gcc/4.9.2-atmel3.5.4)
the conversation iterated over a few codes, and @bricoleau proposed a simplified version of the code showing the weird behavior. here it is
int n = 1;
void setup()
{
Serial.begin(115200);
Serial.println(F("STARTING"));
}
void loop()
{
if ( n <= 3 ) {
boolean r = false;
while ( !r ) {
if (Serial.available()) r = (Serial.read() == 'c' );
}
Serial.println(n);
n++;
} else while (1);
}
you could argue that the active wait on Serial or dead loop to stop the program in the loop at the end are “ugly” but that’s not the point, this is a legit programming construct.
The code as it is should basically greet you with “STARTING” and every time you enter ‘c’ in the Serial console display the value of n
and increase it. Once n reaches 4 the code should go into the infinite else while (1);
loop and be stuck there.
And guess what, when you run it and type ‘c’ a number of times, the code never goes into the infinite loop.
Now if you modify the code to make the boolean r
volatile
int n = 1;
void setup()
{
Serial.begin(115200);
Serial.println(F("STARTING"));
}
void loop()
{
if ( n <= 3 ) {
volatile boolean r = false; // ONLY CHANGE IS r BEING VOLATILE
while ( !r ) {
if (Serial.available()) r = (Serial.read() == 'c' );
}
Serial.println(n);
n++;
} else while (1);
}
then the optimizer cannot make the same assumptions and compiler behaves differently and this time the code does go and get stuck into the infinite loop as expected.
In the french discussion some members looked at the generated binary and it turns out that in the non working version the compiler seems to have removed entirely the if ( n <= 3 ) {
and } else while (1);
parts, leading to the unwanted behavior.
Keeping the code the same and changing the optimizer parameter in the compilation also lead to expected behavior.
So - what do you think is going on there? why would it be legit in that case for the optimizer to get rid of part of the code?