Live data from Hacker News

Undefined behavior in C is a reading error

yodaiken.com

331–340 of 503 posts

Re: Undefined behavior in C is a reading error

#331

Earlier quoted context omitted.

> The obvious intention is that the compiler ignores overflow and lets the processor architecture make the decision. If that were the case, wouldn't signed overflow be implementation-defined or unspecified behavior, instead of undefined behavior? > Assuming that overflow doesn't happen is assuming something false. It's "false" in the same way that assuming two restrict pointers don't alias is "false". It may not be u…

> If that were the case, wouldn't signed overflow be implementation-defined or unspecified behavior, instead of undefined behavior? No, because (among other reasons) the processor architecture might decide to trap or not trap depending the run-time values of configuration registers that the compiler doesn't know and can't control or document.

> the processor architecture might decide to trap or not trap depending the run-time values of configuration registers that the compiler doesn't know and can't control

I'm not certain that that would fall outside implementation-defined behavior. Would something like "Program behavior on overflow is determined by processor model and configuration" not work?

> or document.

And even if the behavior couldn't be documented, that could be covered by unspecified behavior (assuming the language in the C standard is the same as in the C++ standard in this case)

Re: Undefined behavior in C is a reading error

#332

Earlier quoted context omitted.

> given appropriate very specific input data That's the operative words there. Compilers are not required to ensure that, in sufficiently perverse circumstances, undefined behaviour never results in demons flying out of you nose. They are , however, required to not actively put said demons there themselves, because that's part of what distinguishes a programming language implementation from a piece of malware masquer…

Compilers never actively try to put demons in your program. However, they do occasionally end up making constructs that result from a reasonable (if not the most well-thought-out) chain of decisions that end up looking like demons to the untrained eye.

I didn't say "try"; if it quacks like demon, it's a demon, and the implementation is (whether the standards commitee likes it or not) required not to actively put it into programs that didn't already have it[0], deliberately or otherwise.

0: like this one:

  int* zero = 0;
  int bad = *zero; // maybe crash lol
  if(!zero) abort(); // definitely crash lol
  printf("Uln nasaloth geb hai!\n");

Re: Undefined behavior in C is a reading error

#333

Earlier quoted context omitted.

What are they to do, exactly? Optimization is a very 'generic' process and application programmers want optimization. The only sensible thing to do is to assume UB cannot occur and optimize accordingly. What else is there? I can already predict that whatever you suggest will very shortly end up in Halting Problem territory or will mean: No optimization. There are a lot of UBs that (if defined) would require run-time…

C programmers prefer control to "optimization". And if you assume UB cannot occur, you should not generate code that makes it happen. Radical UB is not required for optimization: in fact it appears to mostly do nothing positive. There is not a single paper or study showing significant better performance for substantial C code that depends on assuming UB can't happen - just a bunch of hand waving.

I don't mean to be snide, but there's no paper on it because it's pretty much something you can learn in compiler 101. Without being able to assume that UB doesn't happen, useful optimizations become impossible very quickly.

Re: Undefined behavior in C is a reading error

#334

Earlier quoted context omitted.

> If you are saying that deleting array bounds checks might have performance benefits that outweigh the security concerns, then I disagree. I'm saying that there is existing code in this world in which some variation on /* insanely hot loop where ARRAYSIZE > 32 */ while(true) { ... int x = 1 exists that's currently compiling down to just "a[index] = 1 I'm saying that the authors and their customers are unlikely to be…

There is zero customer demand for less reliable code as a tradeoff for "performance"

Certainly not when C was designed, and arguably not in some cases today as well.

Re: Undefined behavior in C is a reading error

#335

Earlier quoted context omitted.

> If that were the case, wouldn't signed overflow be implementation-defined or unspecified behavior, instead of undefined behavior? No, because (among other reasons) the processor architecture might decide to trap or not trap depending the run-time values of configuration registers that the compiler doesn't know and can't control or document.

> the processor architecture might decide to trap or not trap depending the run-time values of configuration registers that the compiler doesn't know and can't control I'm not certain that that would fall outside implementation-defined behavior. Would something like "Program behavior on overflow is determined by processor model and configuration" not work? > or document. And even if the behavior couldn't be documente…

> Would something like "Program behavior on overflow is determined by processor model and configuration" not work?

Not sure; if nothing else, that seems like it would allow the implementation to avoid documenting any implementation-defined behaviour with a blanket "all implementation-defined behaviour is whatever the hardware happens to do when executing the relevant code".

Re: Undefined behavior in C is a reading error

#336

Earlier quoted context omitted.

Compilers never actively try to put demons in your program. However, they do occasionally end up making constructs that result from a reasonable (if not the most well-thought-out) chain of decisions that end up looking like demons to the untrained eye.

I didn't say "try"; if it quacks like demon, it's a demon, and the implementation is (whether the standards commitee likes it or not) required not to actively put it into programs that didn't already have it[0], deliberately or otherwise. 0: like this one: int* zero = 0; int bad = *zero; // maybe crash lol if(!zero) abort(); // definitely crash lol printf("Uln nasaloth geb hai!\n");

It just isn't that simple in practice. Modern compilers automatically apply a plethora of different rules in sequence when transforming code. This results in a long chain of transformations where each operation is perfectly reasonable when considered on its own. Unfortunately, for certain inputs, the sum total occasionally appears demonic.

The current state of the art is such that there is no way to reliably prevent this that doesn't also severely reduce the optimization abilities of modern compilers. Realistically, adding such language to the standard would (at best) result in worse optimizations by default and additional compiler flags to reenable the more aggressive "nonstandard" ones. (Such flags already exist for various arithmetic operations.)

Re: Undefined behavior in C is a reading error

#337
post #50

I think the reasoning here is flowing backwards. The writer wants to believe that C is a well-designed language suitable for writing large programs (because programmers understandably use it that way; there's not really an alternative to C), and so people reading the spec and finding a minefield _must_ be reading the spec wrong. So many important programs are written in C, and so many of them, with a very strict read…

> The writer wants to believe that C is a well-designed language suitable for writing large programs [...], and so people reading the spec and finding a minefield _must_ be reading the spec wrong.

I think this is the core of the problem. There are languages that provide much more detailed, predictable behaviors, and the author wants to avoid moving to one.

Re: Undefined behavior in C is a reading error

#338

Earlier quoted context omitted.

...and yet the article completely ignores the "with unpredictable results" part and instead spends a lot of time discussing all the other valid consequences (which are also only mentioned as examples, at least in the common understanding of "from ... to ..."). Downthread commenters go into more detail regarding the "ignoring e.g. the possibility of signed overflow may mean to assume that it never happens" reading, so…

Leaving overflow to the processor is an example of ignoring it with unpredictable results. Deleting overflow checks because you assume, incorrectly, that overflow is impossible is not an example of ignoring with unpredictable effects, it does produce unpredictable effects, though.

How is the compiler supposed to know that a particular operation is intended as an overflow check though? It isn't a human and it doesn't actually comprehend the code it operates on. It just blindly applies rules.

I want the compiler to eliminate redundant operations. That's a large part of the point of doing optimizations in my view! Best effort attempts to avoid eliminating obvious sanity checks are desired of course, but I doubt it's feasible to reliably identify those short of AGI. (And at that point, why are you still writing code?)

Re: Undefined behavior in C is a reading error

#339
post #329

Earlier quoted context omitted.

> people who think that silently optimizing away previously functional sanity checks is an acceptable engineering tradeoff To be fair, as several people and TFA have pointed out, this isn't a problem with C, but with defective/malicous C compilers . Admittedly, that's not much help if you can't find a compiler that isn't defective/malicous, though, so I can only wish you the best of luck.

I don't get what you or the comment you're responding to are wishing for. Do you want compilers to stop adding optimizations while staying within the bounds defined by the spec? That they somehow guess that a given piece of code that may trigger UB is too important for them to optimize it based on the assumption that the developer knew what she was doing and ensured that it wouldn't? The case of a compiler update bre…

I want default behavior which does not surprise me. I have come to understand that this probably means I want a different language, because the C spec essentially requires compiler authors to make optimizations which introduce surprising semantics in order to compete on performance with other languages.

It would be fine if I could opt into new semantics — something like Rust's "editions" would resolve my objections about these compiler optimizations. But that doesn't seem to be on offer in the C ecosystem.

Re: Undefined behavior in C is a reading error

#340
post #329

Earlier quoted context omitted.

> people who think that silently optimizing away previously functional sanity checks is an acceptable engineering tradeoff To be fair, as several people and TFA have pointed out, this isn't a problem with C, but with defective/malicous C compilers . Admittedly, that's not much help if you can't find a compiler that isn't defective/malicous, though, so I can only wish you the best of luck.

I don't get what you or the comment you're responding to are wishing for. Do you want compilers to stop adding optimizations while staying within the bounds defined by the spec? That they somehow guess that a given piece of code that may trigger UB is too important for them to optimize it based on the assumption that the developer knew what she was doing and ensured that it wouldn't? The case of a compiler update bre…

> I don't get what you or the comment you're responding to are wishing for.

Quoting from another of my comments:

> > [What are you objecting to?]

> Inferring any propositional statement about the program (eg "this pointer is not null") from the fact that its negation would imply undefined behaviour.

That is what the problem is. Undefined behaviour is a licence to implement operations without regard for unusual corner cases, not to infer the absence of said corner cases from those operations and then apply that 'knowledge' elsewhere.

> I fail to see why one would consider a compiler evolving while conforming to language specification defective or malicious

It's https://en.wikipedia.org/wiki/Malicious_compliance in near-textbook form.

Post reply on HN