4 ms·
> You're mixing up "undefined behavior" and "implementation-defined" behavior. Implementation-defined behavior is fine. "Undefined behavior", as the term is use
by geezerjay 9y ago
> You're mixing up "undefined behavior" and "implementation-defined" behavior. Implementation-defined behavior is fine. "Undefined behavior", as the term is used in the C spec, means that literally anything can happen.
Actually I didn't. My point was rather obvious: the whole point of the standards specifying UB is precisely to let implementations define the behavior themselves.
- aw1621107 9y ago> let implementations define the behavior themselves That's literally the definition of implementation-defined behavior. Undefined behavior really means undefined; in terms of the C language, there are no constraints on behavior. Sure, you might get a result one way on one implementation, but if you rely on that you're technically writing a dialect of C, and need to let the compiler know using flags.
- UncleMeat 9y agoImplementation defined behavior does the same thing for a given implementation. The compiler can produce totally different code every time you compile a program with UB. It can even affect code that is totally unrelated to the UB.
- mattkrause 9y agoI'm not sure I buy that second part. Legalistically, I guess it could (the behavior isn't defined, after all), but typically the optimizer makes some valid-only-if-the-code-is deductions and things snowball from there....
- loup-vaillant 9y ago> the whole point of the standards specifying UB is precisely to let implementations define the behavior themselves. This used to be the case. Signed integer overflow for instance is undefined because some CPUs go bananas when you try that. Other platform performed 2's complement just fine, and we used to be able to rely on this. No longer. See, the standard doesn't say "implementation defined". It doesn't say "undefined on platforms that go bananas, implementation defined otherwise". It says "undefined" period. Signed integer overflow is undefined on all platforms, even your modern x86-64 CPU. Compiler writers interpreted it as a licence to assume it never happens, to help optimisations. For instance: int x = whatever; x += small_increment; if (x < 0) { // check for overflow abort(); // security shut down } proceed(x); // overflow didn't happen, we're safe! Here's what the compiler thinks: int x = whatever; x += small_increment; if (x < 0) { // only true if signed overflow -> false abort(); // dead code } proceed(x); Then the compiler simply deletes your security check: int x = whatever; x += small_increment; proceed(x); Don't listen to Chandler Carruth, nasal demons are real. Some undefined behaviours can encrypt your whole hard drive, assuming they're exploitable by malicious inputs.
- userbinator 9y agoThis is the sort of emotionally-charged fearmongering around UB that really makes any discussion pointless. That example is wrong. Integers can be signed. If a compiler cannot prove x >= 0, then it simply cannot remove that code. Now, if you used unsigned int x = whatever; ... if(x < 0) There would be an obvious case for removing that if.
- teraflop 9y agoA very simple test case demonstrates that GCC can remove tests in the presence of signed overflow, even in ways that change a program's behavior. $ cat undefined.c #include <limits.h> #include <stdio.h> #include <stdlib.h> int main() { int x = INT_MAX; if (x+1 > x) { printf("%d > %d\n", x+1, x); } else { printf("overflow!\n"); } } $ gcc --version gcc (Ubuntu 7.2.0-8ubuntu3.2) 7.2.0 Copyright (C) 2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ gcc undefined.c && ./a.out overflow! $ gcc -O3 undefined.c && ./a.out -2147483648 > 2147483647
- userbinator 9y agoYes, that example is well-known but different; here, the compiler is assuming that x + 1 will always be greater than x, which is entirely something else than the parent's assertion of assuming that x + small_increment will always be positive.
- loup-vaillant 9y agoThe difference doesn't matter, you would know better if you weren't clinging so hard to your beliefs. Here's the "difference": $ cat undefined.c #include <limits.h> #include <stdio.h> #include <stdlib.h> int main() { int x = INT_MAX; if (x+1 < 0) { printf("%d < 0\n", x+1); } else { printf("overflow!\n"); } } $ gcc --version gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 Copyright (C) 2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ gcc undefined.c && ./a.out -2147483648 < 0 $ gcc -O3 undefined.c && ./a.out overflow! The security check is gone all the same.
- hermitdev 9y agoThat's not the point, though. In the case of undefined behavior, a compiler doesn't have to define the behavior or even act consistently (most evident by the behavior of the compiler's optimizer). This is entirely different than implementation defined in that a conforming compiler has to document the behavior they implement and do it consistently.