-
-
Notifications
You must be signed in to change notification settings - Fork 7k
Make signed overflow behave "correctly" #4624
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Fix for issue arduino#4511 In short, the documentation says that signed integer overflow causes the value to "roll over". Actually, this results in undefined behavior, with potentially unpredictable results. This patch adds a GCC option to treat signed integers the "right" way so that they roll over as the documentation claims.
I remember to have this issue. It would be nice to fix it. I dont know it this fixes it (i dont remember our test sketch, it was very weird stuff going on), but it would be very important to fix. |
hey this is excellent! could you guys please accept this pull request? it will solve this issue : #4511 |
original poster said he can update the PR if there is any dev actually willing to do his work and merge it :) |
Conflicts: hardware/arduino/avr/platform.txt
Bump! |
@cmaglie could you have a look at this, please? I think it could cause some potential trouble. |
I think we'd need to do some profiling. On an AVR, certain optimisations being disabled could be quite a problem for many currently working projects that rely on code size or critical timing. This I'd assume would affect most integer arithmetic. |
Personally I don't think this will affect much performance-wise (and in fact it might solve some hidden bugs), but I guess some profiling won't hurt. In any case, this issue must be fixed; Arduino documentation can't tell users they can do something they can't do (so either add the flag or fix the documentation). In case it is found that a piece of code in the libraries does break with this de-optimization, I would:
|
One argument against adding this flag is that it will cause problems when people move code from Arduino to other environments without this flag (also when not moving code per se, but when people start to work in other environments and now have expectations that are not true). This isn't a blocking argument per se, but it's good to realize it. Adding a note to the documentation might be sufficient to tackle this, as well. |
Well, all of the "Arduino language" is specific to Arduino anyway; there are things Arduino lets you do that are not standard (most of them such as types or special methods are part of the main library, but e.g. you don't need to declare a function before using it), so I'd say Arduino is already non-portable, and iiuc the philosophy is to favor ease of use over teaching correct C++. |
Currently the behavior is undefined. With the flag its defined. It does not mean without it could not be the same though. Since arduino is meant for beginners they should get less of those weird errors. you cannot tell how many times i had extremely confusing errors with this and how much time i spent on those errors. Beginners will likely just fail. If you port this code without adding the flag, then its your fault. In general its a bad idea to port arduino code, as the environment has tons of "weird" settings, so that does not matter, it only improves stuff. +1 from my side to add this |
Plus, the way it is, the code is still "not portable" anyway; for the code to be portable it would need to behave consistently across platforms, but UB makes everything unpredictable and potentially inconsistent even on a single platform. (It's good to consider possible regressions and other consequences before applying this change though; nobody likes regressions.) |
What is needed for a decision on this PR? The longer it keeps sitting around unattended, the more prone it is to become obsolete and require constant maintenance (I have already fixed the merge conflicts once and I'm not going to fix them again just to see them appear again). Regardless of whether or not this PR is accepted, Arduino should reflect what the documentation claims it does; otherwise users will get an inconsistent and unexplained behavior. If this is not going to be fixed, at least fix the documentation to stop falsely claiming that ints may "roll over", but procrastinating a decision because "some profiling may have to be done" (and neither doing the profiling nor fixing the documentation) is pointless. |
I tried to compile the example StandardFirmata to test the output size:
without the option in place gcc is actually optimizing a bit more (at least in size, but I guess there is also a bit of speed improvement). If it was at no cost I've had absolutely no concerns in merging it but right now I think that enabling this option will give little-to-zero advantage. Did anyone have an example where the signed-rollover may be of any help? |
Thanks for fixing the documentation; it's a first step.
Either nobody was relying on it, or somebody was relying on it unknowingly, but fortunately the effect was not visible for some reason. (Example: #4605 points out that pinMode() et al check for pin validity in an incorrect way, but undefined behavior only happens if they are actually called with an invalid pin.)
I'll look into that example code to see what may be happening. What board are you compiling for? I get 11092 for the executable + 979 for the static variables on an Arduino/Genuino Uno. GCC has a very powerful tool, the sanitizer, which allows generating an executable that does a lot of extra checks, such as array boundaries or signed overflow with the |
I've compiled for Arduino Leonardo.
interesting the man page says:
so it instruments the code to check for undefined behaviours, is still not clear to me what happens when such condition is detected (how the instrumented code tells that it has detected something). |
Found the cause, or at least part of it. It seems that that example does indeed benefit from this optimization. An analysis of the generated .elf using
Comparing the result of the disassembled output (
then the compiler cannot assume that this is the same as
since this ignores the case where In short: there are probably several small optimizations that could be made, that may or may not be currently causing potential UB. Same applies to other examples. So I don't know what to think; after all we're speaking of a 0.5% size difference, and in exchange we get rid of a case of undefined behavior which may be harmful for new users.
That makes two of us :P
but I have no idea of what |
|
Fix for issue #4511
In short, the documentation says that signed integer overflow causes the value to "roll over". Actually, this results in undefined behavior, with potentially unpredictable results (see #4511 for an example). This patch adds a GCC option to treat signed integers the "right" way so that they roll over as the documentation claims.