Live data from Hacker News

Undefined behavior in C is a reading error

yodaiken.com

361–370 of 503 posts

Re: Undefined behavior in C is a reading error

#361

Earlier quoted context omitted.

Yes, some UB are not decidable at compile time, but a lot could be easily speced to have a defined behavior at runtime, such as overflows. The main reason to not spec these things is because people would be arguing "this makes compiled code on my esoteric 9-bit 1-complement chip slower" or "there was this chip in the 70s that did things differently" or "but a short int on Cray was 64-bit". Great, so now the spec has…

Note that (void *)0 is always NULL, as mandated by the standard. But, to address the content of your comment: defined behavior at runtime is not necessarily good behavior at runtime. Defining signed integer overflow to wrap, for example, is probably a bad idea, because this is rarely the intent of the code. Having all such operations trap might be a good idea, but now you're going to get the same "stop breaking my wo…

Yes, thankfully at least with NULL they didn't fall into the legacy trap and messed up the standard with non-zero NULL that some machines before have been kind of using.

>Defining signed integer overflow to wrap, for example, is probably a bad idea

I wouldn't call it great behavior, but it's at least what most people expect will happen, and most people will be able to understand what's going on, and it's fast on most systems that matter. However, it's still undefined behavior. Just codifying overflows to be wrapping, would therefore be an improvement in my opinion, at least over what we have today.

Re: Undefined behavior in C is a reading error

#362
post #211

Earlier quoted context omitted.

from ISO/IEC 9899:2011 "Programming Languages -- C" 3.4.3 1 undefined behavior behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements 2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner charac…

It's not a huge leap, but it still doesn't mean that UB by definition means that the compiler is allowed to assume UB doesn't happen. Allowing the compiler to assume this is one reasonable result of this definition (I give an example of how this reasoning works somewhere else), but it is not equivalent to the definition of UB, in principle.

The definition logically implies that compilers are allowed to assume UB doesn't happen. The definition is:

> undefined behavior: behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements.

With these optimisations, either:

1. The program contains no UB, the transformed code acts as expected, and the compilation is valid.

2. There's UB; the standard imposes no requirements on what behaviour that translates to; and so the transformed code is valid, regardless of what it does.

Re: Undefined behavior in C is a reading error

#363
post #287

Earlier quoted context omitted.

It goes further than that. The debates around UB a more about whether the compiler can assume that there are no buffer overflows and perform optimizations based on that. For example, if you have a local variable `char buffer[16]`, and there is an access `buffer[i]`, should the compiler be allowed to derive that 0 = 16, why shouldn't it? But some argue that the compiler shouldn't, exactly because such automated formal…

The result is a perpetually unstable situation fostering inevitable errors when the programmer is surprised by the compiler. There's no remedy except to move away from C to more tightly specified languages.

The problem is ecosystems like UNIX based platforms, that will never move to something else.

The only solution is to throw them away, e.g. Android style.

Re: Undefined behavior in C is a reading error

#364
post #245

Earlier quoted context omitted.

> and the commtitee I'd argue that for a document like the C standard, if there's a well-known intended meaning, that is the meaning of the document - any other interpretation is purely academic.

To some extent, though the committee has not moved to make this definition explicit in the standard (UB = behavior the compiler is free to assume can't happen), for one reason or another.

For the same reason that it came into the standard in first place.

No compiler vendor wanted to give up their own C variant "features".

Re: Undefined behavior in C is a reading error

#365

Earlier quoted context omitted.

> meticulously written, previously fine programs With relatively few exceptions, if your program hits undefined behavior, then your program was already doing something pretty wrong to begin with. Signed overflow is a poignant example: in how many contexts is INT_MAX + 1 overflowing to INT_MIN actually sane semantics? Unless you're immediately attempting to check the result to see if it overflowed (which is extremely…

Triggering signed overflow and testing whether it has occurred was how I protected the Delphi RTL memory allocation routines from signed overflow attacks, attacks which if not prevented, lead fairly directly to buffer overruns. The code was written in Pascal and assembly, though, so it was safe from a C compiler.

I am quite thankfull that I learned systems programing via BASIC, Pascal and Assembly before coming to C.

As such my vision of low level coding isn't tainted by the ways of C.

Re: Undefined behavior in C is a reading error

#366
post #287

Earlier quoted context omitted.

For me, the canonical UB example is a buffer overflow. No matter how you define UB, in practice a buffer overflow can result in for example, a system crash or - given appropriate very specific input data - encrypting all the files on your hard drive for a ransom. Requiring compilers to restrict UB to something similar to unspecified behavior (where the behavior is not specified by the standard, but a C implementation…

It goes further than that. The debates around UB a more about whether the compiler can assume that there are no buffer overflows and perform optimizations based on that. For example, if you have a local variable `char buffer[16]`, and there is an access `buffer[i]`, should the compiler be allowed to derive that 0 = 16, why shouldn't it? But some argue that the compiler shouldn't, exactly because such automated formal…

If the array index is unconditional, then sure that seems like a reasonable undefined behavior? If the access is conditional and the compiler can't infer whether the branch is taken, though, then it shouldn't make that assumption.

This reminds me of a bug in the msp430 variant of gcc. The compiler would replace "x <= literal" with "x < literal + 1" because it generated more efficient code. If the literal was UINT_MAX, though, the compiler would trudge ahead and roll over the literal to 0. It would then subsequently reason that the comparison was unconditionally false, and then completely optimize away the nominal path of my code. That was a frustrating day of debugging!

Re: Undefined behavior in C is a reading error

#367
post #329

Earlier quoted context omitted.

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 a…

Only moving away to other languages will do it.

C culture and to certain extent Objective-C and C++ ones are tainted by microptimizaitons while typing, where the compilers are the worst examples.

Unfortunely UNIX and C go together, so those that want to keep UNIX like platforms around bettter fix C somehow.

Re: Undefined behavior in C is a reading error

#368
post #163

Earlier quoted context omitted.

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 n…

That is exactly how C should have kept being used, a portable macro assembler, while leaving everything else on the IT stack for more saner languages.

BCPL was anyway designed to Bootstrap CPL, nothing else.

Re: Undefined behavior in C is a reading error

#369
post #163

Earlier quoted context omitted.

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 n…

Exactly. For example there were programs 30-40 years ago that relied on exact stack layouts. These days everybody would agree they are completely broken. The issue of course is that it is extremely hard to write programs that have no UB. It would be nice for compilers to have an option to automatically introduce assetions whenever they rely on some UB-derived axiom, basically as a sort of lightweight sanitizer. In fa…

We had sanitizers since C exists, 1979 to be more exact.

"Although the first edition of K&R described most of the rules that brought C's type structure to its present form, many programs written in the older, more relaxed style persisted, and so did compilers that tolerated it. To encourage people to pay more attention to the official language rules, to detect legal but suspicious constructions, and to help find interface mismatches undetectable with simple mechanisms for separate compilation, Steve Johnson adapted his pcc compiler to produce lint [Johnson 79b], which scanned a set of files and remarked on dubious constructions. "

-- https://www.bell-labs.com/usr/dmr/www/chist.html

Re: Undefined behavior in C is a reading error

#370

Earlier quoted context omitted.

> It would be nice for compilers to have an option to automatically introduce assetions whenever they rely on some UB-derived axiom Modifying a value from a different thread without synchronization is UB. The compiler assumes this does not happen in order to e.g. move things into registers. Could you elaborate how (and how often) you would like to have this kind of UB-derived axiom ("this value remains the same from…

Obviously you wouldn't be able to catch many, or even most cases. Use-after-free is another case that would be very expensive to detect.

I was using it in 2000,

https://www.parasoft.com/products/parasoft-insure/

21 years later it is still an uphill battle to adopt such technology in C and C++ projects.

Post reply on HN