3 ms·
The various C abuses don't really merit further comments, but compilers could help avoid many similar issues by always printing warnings about undefined or unex
by lazyjones 11y ago
The various C abuses don't really merit further comments, but compilers could help avoid many similar issues by always printing warnings about undefined or unexpected behavior (when warnings are turned on at all), not only when the problem will actually manifest itself due to a high optimization level. This is (or was) probably due to high CPU cost of the required analysis steps.
- deleted 11y ago[deleted]
- twoodfin 11y agoThe problem, as I've heard it, is that all but the most trivial instances of statically detectable UB are only noticeable once optimizations have been performed (or simulated by an analyzer), and at that point they're indistinguishable from potential UB introduced by the optimizations themselves. The compiler does a bunch of inlining, constant propagation, other optimizing transformations... and it ends up with some code paths that statically represent UB. If the original code couldn't display UB (up to the user to get this right), and the transformations preserve the original code's defined behavior (as of course they should), then it's safe to exploit the fact that these paths are impossible for further optimization or dead code elimination. Reversing layers of optimization to decide "Is this UB something introduced by me or by the user?" is not something compilers are traditionally architected to do, nor can they typically perform the analysis necessary to determine if a UB code path from either source is guarded by some high level invariants. In such cases, warnings would be actively harmful, as they'd suggest unneeded corrections.
- Kristine1975 11y agoThis blog post (the third in a series about undefined behavior) talks about why compilers don't always warn on undefined behavior, even when they exploit it: http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_21.html http://blog.llvm.org/2011/05/what-every-c-programmer-should-...
- mikeash 11y agoThis function can invoke undefined behavior: int f(int x) { return x + 1; } So can this one: int get(struct Something *s) { return s->field; } Figuring out when undefined behavior needs a warning and when it's unnecessary because it's known by the programmer to be impossible is a Hard Problem. Especially since the compiler has no idea whether the programmer wrote f() knowing that they'll never pass in INT_MAX, or whether the programmer actually does expect to pass in INT_MAX and expects to receive INT_MIN as the result.
- Spivak 11y agoIn practice, does anyone really assume that their system doesn't have two's compliment overflow behavior? Hell during my intro to C course I took at university they told me I should actually detect overflow by seeing if the signs change.
- mikeash 11y agoI sure hope a lot of people assume their system doesn't have two's compliment overflow behavior, because that is absolutely not guaranteed to be the case, and there are real-world C compilers which will not exhibit that behavior in all circumstances. For example, since overflow is undefined, the compiler can assume that an expression like x > x + 1 is always true. Testing with the version of clang that comes with Xcode 7.2, it does this when compiling with -O3. (Note that this is only true of signed overflow. Unsigned overflow is defined behavior, and all unsigned arithmetic is done modulo 2^n where n is the number of bits in the type.) The underlying machine is, of course, two's complement. But nothing says the compiler must compile code to match how the underlying machine behaves. Unfortunately, whoever taught your intro to C course apparently didn't understand C. This is a frighteningly common occurrence, of course. Most people seem to learn C is a very inconsistent way, and imagine a lot of things about it rather than learning how the language actually works.