5 ms·
Someone says this every time the topic of undefined behaviour comes up. Ignoring the original portability concerns, there's a large of set of optimizations tha
by rcfox 11y ago
Someone says this every time the topic of undefined behaviour comes up.
Ignoring the original portability concerns, there's a large of set of optimizations that are only possible if you can assume that no undefined behaviour occurs.
Accessing past the bounds of an array is undefined, and generally a bad thing to do. If the compiler decides that a block of code could only run if you access outside of the array, why not delete that code? Surely, it'll never run!
Even eliminating array bounds checking is an optimization that requires the assumption that you don't go past the end of the array. Languages like Java and Python pay a premium to ensure you don't do this on each iteration of your for loops.
- titzer 11y agoThere is essentially no C compiler that bounds checks arrays, so your comment is a total red herring. This is not an instance where exploiting UB leads to faster code. And, for Java, JITs do a lot of work to remove bounds checks from loops over arrays so that you end up with the fastest possible machine code.
- pm215 11y agoThe compilers not doing array bounds checks is exactly exploiting UB to give faster code. If out-of-bounds accesses were not UB (ie they had a defined behaviour) the compiler would be required to insert a bounds check in order to catch the case and ensure that the result was whatever the defined behaviour said it had to be. As you say, these days smart compilers can optimise to reduce the overhead of the bounds check; but the original 70s C compilers didn't try to be that smart.
- _yosefk 11y agoThe thing is, reading past the bounds of an array can be harmless at the machine level and useful for optimization. So it being UB means you've got a compiler which can optimize better but the cost is that you tied the programmer's hands, so the programmer's optimization opportunities are in fact reduced. And you didn't even tie them, the annoying thing is, rather you laid traps that they can fall into because of failing to notice them. (I'm not saying C made the wrong tradeoff with declaring this or that UB, just that the tradeoff exists.)
- thoughtpolice 11y ago> Surely, it'll never run! Oh, the hilarious irony of giving language-lawyery, glib responses of "obviously, the code will not run" to users (who probably, you know, wrote code with the intention of it running) - users who are complaining about language lawyering optimizing compilers in the first place. It's like two people reading the same page in a different book or something.
- mikeash 11y agoLet's say I write a function that looks like: int ComputeStuff(int value) { if(value < 27) { long and complex computation specialized for values under 27 return result } else { long and complex computation specialized for values 27 or more return result } } Then I call it from somewhere else like so: int x = ComputeStuff(12); Let's say the compiler decides this is a good candidate for inlining. Since the programmer wrote code with the intention of it running, are you saying that the compiler should not take advantage of the fact that it knows the exact value being passed into the function in this case and can delete half the code knowing it will never run?
- SoftwareMaven 11y agoThat's is not remove code due to undefined behavior, so is an apples/oranges comparison. If we keep your function, but the call looks like this: int value1, value2; value1 = compute_value_1() ComputeStuff(value2) # oops, fat-fingered the '2' Do you really think the author meant to not have ComputeStuff run? Since value2 isn't initialized, it could be optimized out. Yes, in this case, you would get a warning, but it is illustrative of the kinds of things can cause optimizers to do very unexpected things to your code. And it is surprisingly easy to find the UB conditions. It's worth reading through this three-part post called What Every C Programmer Should Know About Undefined Behavior[1] from the LLVM folks to see how UB can screw with you, including removing NULL checks, eliminating overflow checks, and making debugging incredibly difficult to follow. It also explains why they can't just generate errors while optimizing. 1. http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html http://blog.llvm.org/2011/05/what-every-c-programmer-should-...
- deleted 11y ago[deleted]