Live data from Hacker News

Undefined behavior in C is a reading error

yodaiken.com

71–80 of 503 posts

Re: Undefined behavior in C is a reading error

#71
post #42

> license for the kinds of dramatic and unintuitive transformations we’ve seen from the compilers, and any indication that undefined behavior should be a vehicle for permitting optimizations. Does anyone have an example of a time where Clang or GCC actually did something bad upon witnessing undefined behavior, rather than simply doing nothing, as the standard proposes? I ask because every time I've seen people get ma…

A fun historical example: https://feross.org/gcc-ownage/

But yes, generally, UB manifests as "the compiler is allowed to assume this doesn't happen" and the bad stuff is a consequence of doing things following those assumptions, not the compiler going "oops well lol UB time to screw with this person."

Re: Undefined behavior in C is a reading error

#72
post #49

Earlier quoted context omitted.

I'm not sure why syscalls would be UB; it's just not something defined by the C standard. Edit: To clarify, I meant UB in the sense it is typically used in these discussions, where the standard more-or-less explicitly says "If you do X, the behavior is undefined." Not in the literal sense of "ISO C does not say anything about write(2), hence using write(2) is undefined behavior according to the C standard", which see…

So if it is behavior that is not defined by the C standard, would that not make it undefined behavior?

While technically correct, “undefined behavior” in terms of C and C++ refer to what the standard calls out explicitly as undefined, and not a simple “it’s not referenced, therefore it’s undefined.”

For example, signed(?) integer overflow is explicitly undefined by the standard, but as @formally_proven said, just because write(2) isn’t mentioned doesn’t mean usage of it is undefined.

Re: Undefined behavior in C is a reading error

#73

I think the problem is cultural in the C community. C programmers have Stockholm Syndrome around UB optimizations. As TFA notes, "There is No Reliable Way to Determine if a Large Codebase Contains Undefined Behavior" https://blog.llvm.org/2011/05/what-every-c-programmer-should... That's because UB is a bug that occurs as your program runs (e.g. dereferencing a null pointer). You'd have to prove that your program is f…

> But C programmers believe they deserve to be abused this way.

I don't know of any C programmers who think that way. We accept the state of affairs because there is little alternative. We're not going to rewrite our code in another language, because we mostly need to write in C for various reasons. Also Rust inherits LLVM's undefined behaviour, so it's no panacea. We mostly keep adding flags to turn off the most excessive optimisations and pray.

Re: Undefined behavior in C is a reading error

#74
post #49

Earlier quoted context omitted.

I'm not sure why syscalls would be UB; it's just not something defined by the C standard. Edit: To clarify, I meant UB in the sense it is typically used in these discussions, where the standard more-or-less explicitly says "If you do X, the behavior is undefined." Not in the literal sense of "ISO C does not say anything about write(2), hence using write(2) is undefined behavior according to the C standard", which see…

So if it is behavior that is not defined by the C standard, would that not make it undefined behavior?

There is a difference between jargon in context and the use of those words in a general sense. It can be "undefined behavior" in a general sense, but not necessarily "undefined behavior" in the jargon sense.

After all, if I were to use the words "undefined behavior" in a sentence unrelated to the standards, the definition in the standard of "behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements." would be nonsense. Same goes in the other direction.

Re: Undefined behavior in C is a reading error

#75

I think the problem is cultural in the C community. C programmers have Stockholm Syndrome around UB optimizations. As TFA notes, "There is No Reliable Way to Determine if a Large Codebase Contains Undefined Behavior" https://blog.llvm.org/2011/05/what-every-c-programmer-should... That's because UB is a bug that occurs as your program runs (e.g. dereferencing a null pointer). You'd have to prove that your program is f…

You don't get it: if you are ready to give up top performance, you can choose among a multitude of more forgiving languages.

There is simply no point in having a C language with less than top level optimizations.

Re: Undefined behavior in C is a reading error

#76
First: I do dislike how hard it is to avoid some UB / how impractical some of the rules are.

But I also think a lot of discussions of this topic caricaturize compiler writers to a ridiculous degree. Almost describing them to write optimization passes looking for UB so they can over-optimize something, while cackling loudly in glee about all the programs they can break.

The set of people doing so overlaps with the set of people complaining that the compiler doesn't optimize their code sufficiently to a significant degree.

Lots of compiler optimizations need to know the ranges of values, hence logic to infer ranges. One of the sources for that is "can't happen" style logic - which nearly all of the time are things the code author would agree with if they thought long and hard. Not just about the code as written, but also good the code looks like after inlining (across TUs with LTO).

Re: Undefined behavior in C is a reading error

#77

I'm not convinced. The argument seems to hinge to a very large extent on the sentence: > Permissible undefined behavior ranges from A, to B, to C. The observation that "Permissible" has a specific meaning is important and interesting. But what about "ranges from ... to ..."? The author reads this as "Permissible undefined behavior is either A or B or C.", but that seems like a stretch to me. (Unless ISO defines "rang…

>Somehow the author seems to think that this is not what the wording intended, but they also fail to explain what they think should happen here.

What "should" happen is that the implementation-defined behavior in the assert matches the implementation-defined behavior in the calculation. That is, assert(a+100>a) should produce the same result as

  int x = a + 100;
  int y = a;
  if (x > y)
      ;
  else
      printf("assertion failed\n");

Re: Undefined behavior in C is a reading error

#78
post #31

The author suggests that the text following the definition of "undefined behavior", listing the permitted or possible range of undefined behavior, should be read to restrict the consequences. But the first possibility listed is "ignoring the situation completely with unpredictable results". Surely that covers any possible consequences. The author also says: > Returning a pointer to indeterminate value data, surely a…

> For example, if signed integer overflow yielded an unspecified result rather than causing undefined behavior, I wonder if any implementations would be adversely affected. I suspect so - makes it harder to reason about loop counts because the compiler can't necessarily guarantee that an incremented loop counter won't become negative and thus the loop needs to iterate more. E.g. something like for (int i=param; i Tha…

> I suspect so - makes it harder to reason about loop counts because the compiler can't necessarily guarantee that an incremented loop counter won't become negative and thus the loop needs to iterate more.

This is a favourite example that gets thrown around, but for all practical loops GCC and clang seem to have no problem even when you compile with -fwrapv

Re: Undefined behavior in C is a reading error

#79
post #43
post #24

I think the real problem stems from the mismatch between modern processors and the processors C was originally designed for. C programmers want their code to be fast. Vanilla C no longer gives them the tools to do that on a modern processor. Either the language needs to be extended or the compiler needs to get more creative in interpreting the existing language. The latter is the least disruptive and it doesn't stop…

When compiler writers have get "creative" with C undefined behavior, programming C no longer produces predictable results. > least disruptive Like starting to optimize away loop checks that can "never happen" because signed integer overflow is UB, suddenly changing the behavior of programs that were fine for years? I wish I could just fence off this insanity by never starting another project in C. Unfortunately, C is…

> Like starting to optimize away loop checks that can "never happen" because signed integer overflow is UB, suddenly changing the behavior of programs that were fine for years?

Yeah. Not doing that on modern processors is actually quite disruptive.

Here:

    for(i = offset; i 
What C compilers currently do is, in line with the standard, ignore the case that offset + 16 might overflow. This makes this eligible for loop unrolling, and depending on the specifics of the math inside the loop, the compiler can do a lot to pre-calculate things because it knows this is happening 16 times exactly.

If, instead, we force compilers to think about the fact that offset + 16 could have some implementation-defined meaning like wrapping, then all bets are off & we have to throw a bunch of optimization opportunities out the window.

Lots and lots of hot & tight loops which are currently able to be compiled into something suitable for the preferences of modern CPUs instead has to be to be naively compiled because of the need to hold back due to the possibility of something that largely wasn’t happening, happening.

Most people write most loops this way, never expecting or intending to overflow anything. Most loops are benefitting from this optimization. A lot of code would get slower, and programmers would have to do a lot more fragile hand-unrolling of operations to get that performance back. And they’d need to update that more often, as whatever the optimal “stride” of unrolling changes with the evolution of CPU pipelines.

It’s slower code and more work more often for more people, to satisfy a minority use-case that should really just have its own separate “please wrap this” construct.

Re: Undefined behavior in C is a reading error

#80

I think the problem is cultural in the C community. C programmers have Stockholm Syndrome around UB optimizations. As TFA notes, "There is No Reliable Way to Determine if a Large Codebase Contains Undefined Behavior" https://blog.llvm.org/2011/05/what-every-c-programmer-should... That's because UB is a bug that occurs as your program runs (e.g. dereferencing a null pointer). You'd have to prove that your program is f…

Anecdotally, I find about as many bugs in my Java code at work, as I do in my hobby C code, including "dereferencing null pointers" aka NullPointerExceptions.

NPE isn't really a relevant comparison point - it raises an exception of sorts in both languages. Accessing an array past its end, accessing freed memory, reading uninitialized memory seem more apt.
Post reply on HN