iteration 647 invokes undefined behavior

I have the following sketch:

// Basic Arduino
#include "Arduino.h"
// Serial port debugging
#include <SoftwareSerial.h>

void setup() {
 // put your setup code here, to run once:
 Serial.begin(9600);
 Serial.println("Set up complete");
}

void loop() {
 // put your main code here, to run repeatedly:
 unsigned long tickMillis;
 signed long actMillis;

 actMillis = 2147483000;
 tickMillis = actMillis;
 int spacer;
 int counter;
 for (counter=1;counter < 1000;counter++)
 {
   Serial.print("ActMillis=");
   Serial.print(actMillis,DEC);
   Serial.print(",tickMillis=");
   Serial.print(tickMillis,DEC);
   Serial.print(",tickMillis+150=");
   Serial.print(tickMillis+150,DEC);
   Serial.print(",counter=");
   Serial.print(counter,DEC);
   Serial.println(".");
 
   if (actMillis != tickMillis){
     Serial.println("ERROR 4");
   }
   
   if (actMillis > tickMillis){
     Serial.println("ERROR 5");
   }
   
   if (actMillis < tickMillis){
     Serial.println("ERROR 6");
   }
    if (tickMillis != actMillis){
     Serial.println("ERROR 7");
   }
   
   if (tickMillis > actMillis){
     Serial.println("ERROR 8");
   }
   
   if (tickMillis < actMillis){
     Serial.println("ERROR 9");
   }
   
   actMillis++;
   tickMillis++;
 
   if (counter > 1000){
     Serial.println("Exceed");
   }
 
 }

 Serial.println("ERROR 10");

}

Which compiles with the following warning and loads to the board:
O:\Arduino\sketch_jul19a\sketch_jul19a.ino: In function ‘loop’:

O:\Arduino\sketch_jul19a\sketch_jul19a.ino:58:16: warning: iteration 647 invokes undefined behavior [-Waggressive-loop-optimizations]

actMillis++;

^

O:\Arduino\sketch_jul19a\sketch_jul19a.ino:23:3: note: containing loop

for (counter=1;counter < 1000;counter++)

^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\main.cpp: In function ‘main’:

O:\Arduino\sketch_jul19a\sketch_jul19a.ino:58:16: warning: iteration 647 invokes undefined behavior [-Waggressive-loop-optimizations]

actMillis++;

^

O:\Arduino\sketch_jul19a\sketch_jul19a.ino:23:3: note: containing loop

for (counter=1;counter < 1000;counter++)

^


My problem is that NONE of the condition tests work. The loop just runs indefinitely. When I run the program as is the value of actMillis and tickMillis both increase indefinitely as does counter. I extracted the code out of a larger program because it was not working, to try to isolate the error. In the larger program actMillis flipped negative(as expected) but again NONE of the conditions tripped.

This kind of optimisation does not seem correct to me.

I was trying to test out overflow with millis but don’t want to wait 49 days to have it overflow before the error occurs.

Can anyone help? I want to turn off the optimisation at least while I am coding and debugging.

You’ve declared actMillis to be a signed long integer and initialized it to 2147483000. The largest integer a signed long can hold is 2147483647.
When you increment that value, the result becomes negative which is why the compiler is complaining.
Why did you declare actMillis to be signed?

Before you post any more code, read how to post code properly and then use the </> icon to create [code]...[/code] tags around your code so that it is easier to read.

Pete

Point noted on the code posting.

Thanks for replying.

I defined it as signed because I was trying out comparisons between signed and unsigned numbers. I don't have a real reason to do it other than testing an idea but I certainly have done it with byte values in the past on other platforms, with good reason.

I am happy for the compiler to warn me that something funny is going on but the net result is that the code it has generated has ALL the conditional statments hard coded to false.

None of the IF's trip nor does the exit condition on the loop, the program just loops forever.

This can not be right.

Tune:
None of the IF's trip nor does the exit condition on the loop, the program just loops forever.

This can not be right.

Do you not understand the whole setup/loop construct? Looping forever is EXACTLY what loop does, and is absolutely 100% "right"....
Regard,
Ray L.

Ray, thanks for replying. I understand the loop() function runs forever.

My problem is that the embedded for loop

for (counter=1;counter < 1000;counter++)
  {
 
 
  }

which I coded also runs forever. The Serial.print statements just keep coming and include values of counter way past 1000.
Also

 Serial.println("ERROR 10");

Which exists outside my for loop is NEVER executed.

I would expect it to be executed each time the counter reaches 1000 and the for loop terminates. but the for loop never terminates, counter just keeps increasing forever.

But, then again, the compiler warned you: "iteration 647 invokes undefined behavior"

Fix THAT problem first, then see what happens. "Undefined behavior" means "all bets are off", and you can no longer depend on the code to do what you would normally think it would do...

Regards,
Ray L.

OK, So I have managed to find optimisations and disable them. The program now partially works.

this is the output I get:

Set up complete
ActMillis=2147483000,tickMillis=2147483000,tickMillis+150=2147483150,counter=1.
ActMillis=2147483001,tickMillis=2147483001,tickMillis+150=2147483151,counter=2.
ActMillis=2147483002,tickMillis=2147483002,tickMillis+150=2147483152,counter=3.
ActMillis=2147483003,tickMillis=2147483003,tickMillis+150=2147483153,counter=4.
:
ActMillis=2147483645,tickMillis=2147483645,tickMillis+150=2147483795,counter=646.
ActMillis=2147483646,tickMillis=2147483646,tickMillis+150=2147483796,counter=647.
ActMillis=2147483647,tickMillis=2147483647,tickMillis+150=2147483797,counter=648.
ActMillis=-2147483648,tickMillis=2147483648,tickMillis+150=2147483798,counter=649.
ActMillis=-2147483647,tickMillis=2147483649,tickMillis+150=2147483799,counter=650.
ActMillis=-2147483646,tickMillis=2147483650,tickMillis+150=2147483800,counter=651.
ActMillis=-2147483645,tickMillis=2147483651,tickMillis+150=2147483801,counter=652.
:
ActMillis=-2147483301,tickMillis=2147483995,tickMillis+150=2147484145,counter=996.
ActMillis=-2147483300,tickMillis=2147483996,tickMillis+150=2147484146,counter=997.
ActMillis=-2147483299,tickMillis=2147483997,tickMillis+150=2147484147,counter=998.
ActMillis=-2147483298,tickMillis=2147483998,tickMillis+150=2147484148,counter=999.
ERROR 10
ActMillis=2147483000,tickMillis=2147483000,tickMillis+150=2147483150,counter=1.
ActMillis=2147483001,tickMillis=2147483001,tickMillis+150=2147483151,counter=2.
ActMillis=2147483002,tickMillis=2147483002,tickMillis+150=2147483152,counter=3.
ActMillis=2147483003,tickMillis=2147483003,tickMillis+150=2147483153,counter=4.
:

I don’t understand why when actMillis goes negative the following line is not executed:

    if (actMillis != tickMillis){
      Serial.println("ERROR 4");
    }
    
 //   if (actMillis > tickMillis){
 //     Serial.println("ERROR 5");
 //   }
    
    if (actMillis < tickMillis){
      Serial.println("ERROR 6");
    }
     if (tickMillis != actMillis){
      Serial.println("ERROR 7");
    }
    
    if (tickMillis > actMillis){
      Serial.println("ERROR 8");
    }
    
//    if (tickMillis < actMillis){
//      Serial.println("ERROR 9");
//    }

I would expect all the non-commented-out sections to trigger and produce output but you can see from the output that they do not.

(I included the comparisons twice with each variable on either side of the condition in case it was defaulting to the first variable type to make the comparison.)

I got the following warning 16 times which made me wonder if it would execute at all, it seemed very unhappy.

In file included from C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/USBAPI.h:27:0,

                 from C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:233,

                 from O:\Arduino\sketch_jul19a\sketch_jul19a.ino:2:

c:\program files (x86)\arduino\hardware\tools\avr\avr\include\util\delay.h:112:3: warning: #warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed" [-Wcpp]

 # warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"

   ^

RayLivingston:
But, then again, the compiler warned you: "iteration 647 invokes undefined behavior"

Fix THAT problem first, then see what happens. "Undefined behavior" means "all bets are off", and you can no longer depend on the code to do what you would normally think it would do...

Regards,
Ray L.

I have removed the warning, by disabling optimisations but it still doesn't work.

None of the IF statements trigger even when actMillis is negative and tickMillis is positive.

In C and C++, when you compare signed and unsigned integers of the same size, the signed integer will be converted to unsigned before it's compared to the unsigned value. So you're getting the expected results.

Tune:
I defined it as signed because I was trying out comparisons between signed and unsigned numbers.

No, don't even think of doing that, be consistent with signs or you'll just get grief. No machine
I know implements comparison between signed and unsigned in hardware, so the low level operation doesn't
exist.

C will just widen the types, meaning one of the operands to the comparions is hard-casted to the
wrong type before the comparison - I'm not sure if this will even happen consistently, it may be
a language area which is simply not defined.