Avoid signed integer overflow in example sketch#5
Avoid signed integer overflow in example sketch#5edgar-bonet wants to merge 1 commit intooymotion:masterfrom
Conversation
The `int' type is only 16-bits long in some Arduinos. On those devices, the square of an analog reading, filtered or not, may not fit in an `int'. Use `long' instead, in order to avoid signed integer overflow, which in C++ is undefined behavior.
|
According to the letter of the C++ standard, anything (really anything!) can happen in the presence of undefined behavior. Accordingly, it may seem futile to try to second-guess what the compiler may be thinking. In this case, however, the compiler behavior turns out to be understandable. Taking a look at what it did can give some insight on the kind of surprises that undefined behavior can produce. In this case, the filter returned 223. Then the line int envelope = sq(dataAfterFilter);computed the square of 223, which is 49729 (larger than if (n < 0) {
int t = print('-');
n = -n;
return printNumber(n, 10) + t;
}
return printNumber(n, 10);And here is where things break apart: |
|
Hehe, I ran into this issue a few months ago after I yoinked the example code for a project I'm working on. Wish I had read this pull request back then instead of going down the rabbit hole of debugging it myself 😅. |
Running the example sketch SimpleEMGFilters.ino on an Arduino Uno, I got the output:
The last line is suspicious: not only is it too large to be plausible, it is even way larger than
INT_MAX, which should not be possible for anint.Further investigation revealed the source of the problem to be an integer overflow in the computation of the square of
dataAfterFilter. Signed integer overflow is undefined behavior in C++. Undefined behavior means that anything can happen, including “impossible” results like above.Computing the square as a
longsolves the issue.