Edit: I was responding to someone saying `(INT_MAX+1)` was implementation defined so couldn't go skynet; and I was asking honestly because the C standard is twisty as heck and maybe they knew something I didn't.
___
Isn't it undefined because of signed integer overflow? Or at least implementation defined whether it's undefined or not?
The C standard (n1570) even uses integer overflow as an example of undefined behavior in section 3.4.3
> An example of undefined behavior is the behavior on integer overflow
> undefined behavior in C/C++ is that it simplifies the compiler’s job, making it possible to generate very efficient code in certain situations.
I've been growing more skeptical of this claim over time. First, more evidence would be nice instead of "some loops". What is a program (not a benchmark) that has an observable performance difference when compiled with and without -fwrap?
Second, it seems counter productive. The word is now out that if you use signed ints, the compiler is going to fuck you over. So now everybody is (or should be) using unsigned ints, and whatever optimization the compiler was performing, now it can't. A lot of grief for no progress.
> I've been growing more skeptical of this claim over time. First, more evidence would be nice instead of "some loops". What is a program (not a benchmark) that has an observable performance difference when compiled with and without -fwrap?
Google brings up this old message. It seems to affect the SPEC2000 suite fairly badly. SPEC2000 mostly measures real applications, such as gzip, and is not a series of microbenchmarks.
Interesting, though I still wonder to what extent this is a result of optimizations chasing SPEC. Alternatively, could similar optimizations be made to work with defined behavior? (How will rust fair with "less undefined" behavior?) As I mentioned, it's kind of crazy that I might substantially impair the performance of gzip by changing a few ints to unsigned.
I really like your second point. That's kind of a difficult failure case to try and mitigate.
I've been vaguely concerned with how to ensure my C code avoids undefined behavior, but it didn't occur to me that I also need to watch out in being overly conservative because then I'll be causing the optimizers trouble.
I'm not trying to disparage anyone who is actually able to be productive in a C environment, but I'm really hoping something like Rust is able take over that development space.
Isn't complaining that (INT_MAX + 1) is undefined the same as complaining that (8/0) is undefined? What meaningful functionality could be gained by defining overflow behavior? If you really want to know what INT_MAX + 1 is, try:
I'm only speaking for my personal preferences here.
My two problems with undefined behavior is that 1) it is not always obvious that your program is guilty of undefined behavior and 2) when a C program contains undefined behavior the compiler can generate surprising machine code.
I don't have any problem with 8/0 being undefined mathematically, but I do have a problem with a C compiler generating code that will delete my hard drive if it ever occurs (an unlikely but theoretically possible for a conforming C compiler).
INT_MAX + 1 is problematic because most people expect wrap around (and in fact they may be using a compiler that does this). It's more problematic because UINT_MAX + 1 does get wrap around. And finally there's a bunch of difficult to remember auto integer conversion rules. Taken together it's not surprising that many people will find it difficult to determine if their integer usage is correct.
One solution is of course to use a safer language than C (where I unfortunately have to end up). But I personally object to the idea that you have to have undefined behavior in order to get the performance of C (waiting to see how the development of languages like Rust goes to determine if I'm right).
There exists an enormous body body of reliable and fast code written in "C" (e.g. the Linux kernel). I've been coding in C for 27 years, C++ for 20. I think the idea that a language can permit only useful work to occur is naive. In order to code well, the programmer must understand how the computer works, and have a great deal of focus. If you have those, "helpful" languages only seem to get in the way.
I think a good middle-ground would be to have more narrowly scoped behavior. Not quite implementation-defined (as I believe that requires the implementation to be consistent in its treatment?) but for instance "Integer overflow will result in the integer taking an unspecified (and potentially changeable) valid value for that integer". I'm not sure whether that particular example sufficiently covers the requirements of the optimiser, but defining it as "May cause any of the following results, but not nasal demons" would perhaps be an improvement?
DISCLAIMER: I haven't done any C programming in years, and I wasn't particularly good at it, even then.
12 comments
[ 2.9 ms ] story [ 36.6 ms ] threadhttp://blog.llvm.org/2011/05/what-every-c-programmer-should-...
___
Isn't it undefined because of signed integer overflow? Or at least implementation defined whether it's undefined or not?
The C standard (n1570) even uses integer overflow as an example of undefined behavior in section 3.4.3
> An example of undefined behavior is the behavior on integer overflow
I've been growing more skeptical of this claim over time. First, more evidence would be nice instead of "some loops". What is a program (not a benchmark) that has an observable performance difference when compiled with and without -fwrap?
Second, it seems counter productive. The word is now out that if you use signed ints, the compiler is going to fuck you over. So now everybody is (or should be) using unsigned ints, and whatever optimization the compiler was performing, now it can't. A lot of grief for no progress.
Google brings up this old message. It seems to affect the SPEC2000 suite fairly badly. SPEC2000 mostly measures real applications, such as gzip, and is not a series of microbenchmarks.
http://www.archivum.info/autoconf-patches@gnu.org/2007-01/00...
I've been vaguely concerned with how to ensure my C code avoids undefined behavior, but it didn't occur to me that I also need to watch out in being overly conservative because then I'll be causing the optimizers trouble.
I'm not trying to disparage anyone who is actually able to be productive in a C environment, but I'm really hoping something like Rust is able take over that development space.
printf("INT_MAX+1= %lld\n", (long long)INT_MAX + 1LL);
My two problems with undefined behavior is that 1) it is not always obvious that your program is guilty of undefined behavior and 2) when a C program contains undefined behavior the compiler can generate surprising machine code.
I don't have any problem with 8/0 being undefined mathematically, but I do have a problem with a C compiler generating code that will delete my hard drive if it ever occurs (an unlikely but theoretically possible for a conforming C compiler).
INT_MAX + 1 is problematic because most people expect wrap around (and in fact they may be using a compiler that does this). It's more problematic because UINT_MAX + 1 does get wrap around. And finally there's a bunch of difficult to remember auto integer conversion rules. Taken together it's not surprising that many people will find it difficult to determine if their integer usage is correct.
One solution is of course to use a safer language than C (where I unfortunately have to end up). But I personally object to the idea that you have to have undefined behavior in order to get the performance of C (waiting to see how the development of languages like Rust goes to determine if I'm right).
DISCLAIMER: I haven't done any C programming in years, and I wasn't particularly good at it, even then.