Live data from Hacker News

Undefined behavior in C is a reading error

yodaiken.com

161–170 of 503 posts

Re: Undefined behavior in C is a reading error

#161
post #139

Earlier quoted context omitted.

> 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 don't know if there exists a C compiler that leverages this feature but there are ISAs (for instance MIPS) that can trap on signed overflow. The fact that it's UB in C means that you can tell the compiler to generate these exception-generating instructions, which could make some overflow bugs easier to track down without any performance implications. And your compiler would still be 100% compliant with the standard…

That doesn't really help with the compiler optimization aspect : A typical use of the range information would be to unroll the loop - in which case there's no addition to trap on anymore.

Re: Undefined behavior in C is a reading error

#162
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…

Sounds like you're interested specifically in https://blog.tchatzigiannakis.com/undefined-behavior-can-lit...

Re: Undefined behavior in C is a reading error

#163

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…

The current situation is not good for compiler writers either. But nobody has ever shown that either C programmers want to sacrifice safety for "optimizations", or that these UB optimizations actually improve performance of anything.

What do you mean by "these UB optimizations"? C is a low-level language; it's basically impossible for a compiler to reason about the code unless it makes certain assumptions. It needs to assume the code is not self-modifying to do pretty much any code-generation more intelligent than a macro assembler. It needs to assume the code isn't messing with the stack frames/return addresses in order to inline functions. It needs to assume the code isn't using an out-of-bounds pointer to access a neighboring local variable, so that it can move local variables into registers. "gcc -O0" is a good approximation for the performance you get if the compiler isn't allowed to optimize based on UB.

Yes, that means C without optimizing without UB is slower than Java. Optimizations need some form of reasoning about what's happening. For Java it's optimizing based on guarantees provided by the language (there's no raw pointers that could mess with the things listed above). But C doesn't provide any hard guarantees, so instead it needs to blindly assume that the code will behave sanely.

Also note that for many of the more manageable sources of UB, most compilers provide a choice (-fwrapv, -fno-strict-aliasing, ...). Yet few projects use these options, even when they use other gcc/clang-specific features. Doesn't that indicate that C programmers indeed want to sacrifice safety for optimizations?

Re: Undefined behavior in C is a reading error

#164
post #48

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…

What do you think UB is if not something where the behaviour is not defined?

So is everything UB since all hardware isn’t perfect?

Re: Undefined behavior in C is a reading error

#165
Quoting from the same passage in the standard as the article does:

> Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to ...

Ignoring the situation completely with unpredictable results seems like it covers the current compiler behavior.

The author does not like how current compilers work. But his argument against it mixes "it would be better if it worked differently" with "A specific pedantic reading of the standard says they are wrong". The second kind of argument seems to undercut his wider point. For his wider point is "Compilers should be reasonable rather than turning on pedantry". At least, that is what I think his point is, and it seems like the much stronger argument to me.

Trying to "trip up" the proponents of current behavior by pointing to a possible miss-reading of a comma is not going to do much. Arguing instead that their practice is harmful seems like a much more likely to work approach. That said, such an argument should probably be civil. The article links to this [1] discussion. The link is supposed to show the peculiar arguments used by proponents of current behavior. What I read there is someone lashing out, calling names, and grand-standing. Convincing compilers to be more reasonable is probably going to require a very different tone. Not one of "how dare you be so stupid" but one of "perhaps you could consider this side-effect of current behavior" and "have you considered this approach".

[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=30475

Re: Undefined behavior in C is a reading error

#166

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…

> But I also think a lot of discussions of this topic caricaturize compiler writers to a ridiculous degree. The inflamed backlash should tell you just how damaging it is to impose silent failure on meticulously written, previously fine programs.

If the program was previously "fine" on version x.y.z of some compiler, then it is most likely still fine on it. That's the target that the program was written for.

There's some disagreement on whether you can call a program "fine" that breaks after switching to a newer version, or a different compiler.

I see a lot of programmers out there that unfortunately use the behavior of their code on whatever compiler they're using at the moment as a proxy for what the language actually guarantees.

Re: Undefined behavior in C is a reading error

#167
post #39
post #6

Earlier quoted context omitted.

The thing about UB is that it tends to happen when the C standard refuses to specify when a program segment is erroneous or valid. Some C environments treat memory as a large array of undifferentiated bytes or words, by design. Other C environments have tagged, bounds-checked regions of memory, again by design. (For example, the C compiler for the Lisp machine.) Usually, indirecting through a null pointer or walking…

> The idea that UB is carte blanche for implementations to do whatever is an unintended consequence of the vague language of the standard. Whether or not this was originally intended, it's certainly become the way the standard is written and used today, so that's kind of beside the point. Further, this is not some new idea that arose from the C standard. It's a basic, core idea in both software engineering and comput…

One issue is that under the prevailing interpretation, the existing semantics is not reliable. You do not know when or if the compilers will take advantage of UB to completely change the semantics they are providing. That's not tenable.

Re: Undefined behavior in C is a reading error

#169
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…

e.g. removing a check for for overflow is definitely NOT ignoring the behavior. Deleting write because it would be undefined behavior for a pointer to point at some location is also NOT ignoring the behavior. Ignoring the behavior is exactly what the rationale is describing when it says UB allows compilers to not detect certain kinds of errors. Returning a pointer is certainly a use. In any event, the prevailing inte…

> e.g. removing a check for for overflow is definitely NOT ignoring the behavior. Deleting write because it would be undefined behavior for a pointer to point at some location is also NOT ignoring the behavior.

Depending on how you look at it, this is ignoring the behavior.

For example, say you have this:

    int f(int a) {
        if (a + 1 
You have 2 situations:

    1. a + 1 overflows
    2. a + 1 does not overflow
Situation 1 contains undefined behavior. If the compiler decides to "ignor[e] the situation completely", then Situation 1 can be dropped from consideration, leaving Situation 2. Since this is the only situation left, the compiler can then deduce that the condition is always false, and a later dead code elimination pass would result in the removal of the error handling code.

So the compiler is ignoring the behavior, but makes the decision to do so by not ignoring the behavior. It's slightly convoluted, but not unreasonable.

Re: Undefined behavior in C is a reading error

#170
post #4

The author seems to be missing this essential text: "the implementor may augment the language by providing a definition of the officially undefined behavior." Making a system call is undefined behavior in the C standard, but it's not undefined behavior in clang-on-FreeBSD, because the implementors of clang on FreeBSD have defined what those system calls do. Ditto for "asm" (UD unless/until you're running on a compile…

> all of the tricks which make "malloc" work, What are those, exactly? AFAIK, you can safely track memory addresses by storing them as intptr_t/uintptr_t.

The C standard says very little about how those types work. In particular, you can cast a pointer to one of them and then cast back to a pointer -- but only if you cast the exact same value back, and the intptr values are not guaranteed to be in any way meaningful.

In particular, casting a pointer to intptr_t, doing arithmetic on it, and casting back is not guaranteed to do anything useful. It almost certainly will, since most systems treat it as roughly the same as casting to char *, but the standard does not guarantee it.

Post reply on HN