Integer overflow - 2+1 Traps for young players (like me)

I had to do some testing with different settings (I did this a bit generic and careless, admittedly).
For some reason, I fell into a number of traps.
I hope you can avoid them. The last trap in particular is irritating.
Let us begin -
What do you expect as a result of this?

int8_t i8 =  1000000000    ;
int8_t i8f = 1000000000.0f ;

I expected both to go into overflow 127 since it is a signed int8.
Let's output that

void loop() { 
Serial.println("Starting Trap Check");
int8_t i8 =  1000000000    ;
int8_t i8f = 1000000000.0f ;

Serial.print("I8 Special  : "); Serial.print(i8);Serial.println();
Serial.print("I8 Specialf : "); Serial.print(i8f);Serial.println();

gives us:

Starting Trap Check
I8 Special  : 0
I8 Specialf : 127

Trap 1 - different handling of number range overruns

Now I will divide by i8.
What is known for division by 0? Yes, do not perform it - because, if there are results, they are either chaos or annihilation or both. (Spoiler: Both).
This we run:

void loop() { 
Serial.println("Starting Trap Check");
int8_t i8 =  1000000000    ;
int8_t i8f = 1000000000.0f ;

Serial.print("I8 Special  : "); Serial.print(i8);Serial.println();
Serial.print("I8 Specialf : "); Serial.print(i8f);Serial.println();
Serial.println("I m goin to devide by zero");

int8_t z8=0;
z8 = i8f/i8;
Serial.print("z8 Special");Serial.print(z8);Serial.println();

It gives us:

Starting Trap Check
I

-> Processor hangs in a final way because of integer divide by 0 -> Trap 2
And yes, that's it and all. Just an I the start character of "I8 Special". Not more.

-> Trap 3 -
Not all serial prints from before are fully executed.
Serial.print() seems to run in some kind of background queue, and if this queue is not yet fully processed at the moment the processor hangs (as in my case, when the processor stopped working because of the division by 0), you get no output and no clear indication of the cause.
If you are trying to debug in complex situations with Serial.print, it can be helpful to keep this in mind. :slight_smile:
By the way, it is much more fun when ISR are suspicious :woozy_face:

Martin

If you suspect you are losing some Serial output in a crash, put "Serial.flush();" after each message. That will wait until the serial output buffer is empty.

IIRC, C does not define the behavior of signed integer overflow. I think that every implementation that I've seen simply copies the low byte(s) of large integers when an assignment is made to a smaller integer (which explains 0, since 1000000000 = 0x0x3B9ACA00)
You may have been luckier WRT formal behavior of overflowing floats to integers; floats are highly standardized and there are RULES that even small CPUs try to follow.

integer divide by 0 -> Trap 2

What CPU are you using? Neither AVR nor Cortex-M0 has a "trap on divide by zero" feature (heh. Neither one has a "divide" instruction!) I'm not sure about other CPUs. Having an exception occur when there is no exception handler defined is a pretty common way to "crash" a microcontroller, and I don't know whether any CPUs that DO implement Div0 traps actually gave a handler defined to do anything meaningful (what would you do?)

Heh. I looked at the object code (for AVR). Apparently, the compiler determines AT COMPILE TIME that you have done a division-by-zero, and calls the "abort()" function instead of actually attempting to do the divide. But this is NOT what would happen if you forced the divide to actually happen; the AVR divide function doesn't seem to be smart enough to detect div0 (or it is so smart that it decides on other behavior.)
If you make your variables "volatile", for instance, you'll get output like:

Starting Trap Check
I8 Special  : 0
I8 Specialf : 127
I m goin to devide by zero
z8 Special-1

The standard says it is Undefined Behaviour, this makes it pointless to discuss

I have tested all suggestions.
@John,
Serial.flush() did the job, and in case of strange errors where "Serial.print" doesn't seem to work, this can be an essential to get a better idea of root cause.
@Bill,
yepp. Thats it.
I did 2 tests -
I used the volatile data attribute and
Did some calculations to get "0" for i8.
Result exactly as per your description. Both cases a "-1". The processor did not hang or halt
So far all OK.

Anything else ... Yes.
It is just to improve my knowledge :slightly_smiling_face:
Since it is the compiler that implements the abort() function, is there any way to get the compiler to issue a warning either at compile time or at run time?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.