Live data from Hacker News

Everything in C is undefined behavior

blog.habets.se

251–260 of 748 posts

Re: Everything in C is undefined behavior

#251
post #113

Yes there is tons of surprising and weird UB in C, but this article doesn't do a great job of showcasing it. It barely scratches the surface. Here's a way weirder example: volatile int x = 5; printf("%d in hex is 0x%x.\n", x, x); This is totally fine if x is just an int, but the volatile makes it UB. Why? 5.1.2.4.1 says any volatile access - including just reading it - is a side effect. 6.5.1.2 says that unsequenced…

I think the article's point is that you don't actually have to get weird at all to run into UB. Lots of people mistakenly think that C and C++ are "really flexible" because they let you do "what you want". The truth of the matter is that almost every fancy, powerful thing you think you can do is an absolute minefield of UB.

My go-to example of "UB is everywhere" is this one:

    int increment(int x) {
        return x + 1;
    }
Which is UB for certain values of x.

Re: Everything in C is undefined behavior

#253
Some of the C++ code in this article has not been idiomatic in over a decade, and would be considered a code smell today. The language has evolved into quite a different language than when it was first created. As soon as I saw all of those raw pointers and direct pointer access, it was clear that at least part of this article should be taken with a grain of salt.

The other obvious issue with the overall perspective is that C and C++ are being thrown together directly as if somehow they’re nearly the same language, but they are really very far apart nowadays.

Re: Everything in C is undefined behavior

#254

Earlier quoted context omitted.

> -Denial: "I know what signed overflow does on my machine." Or you just not skip the introductory pages, that tell you what the language philosophy of C is, and why there is UB. Yes, UB can be a struggle, but the first four steps are entirely unnecessary. It means that you do not actually understand the core concepts of the very same language you are using, which is kinda stupid.

I think the issue has been that the line between de-jure and de-facto behaviours has shifted over the years as compiler optimizations suddenly began relying on de-jure intrepretations of UB to increase performance while ignoring de-facto usage of the language. When that started happened people became alarmed (oMG UB iS TeH BAD!) and since some old UB machines still had industry support (of organisations that actually…

> I think the issue has been that the line between de-jure and de-facto behaviours has shifted over the years as compiler optimizations suddenly began relying on de-jure intrepretations of UB to increase performance while ignoring de-facto usage of the language.

I guess I am too young, and also too much a purist, because I start from the impression of what the language is, not what the implementations happen to do.

> Personally I think the industry would've benefited from a Boring C (as described by DJB) push by people that would've created a public parallell "de-jure" standard that would've had a chance to be adopted by compiler creators.

-O0

Re: Everything in C is undefined behavior

#255
post #182
post #113

Yes there is tons of surprising and weird UB in C, but this article doesn't do a great job of showcasing it. It barely scratches the surface. Here's a way weirder example: volatile int x = 5; printf("%d in hex is 0x%x.\n", x, x); This is totally fine if x is just an int, but the volatile makes it UB. Why? 5.1.2.4.1 says any volatile access - including just reading it - is a side effect. 6.5.1.2 says that unsequenced…

Yes, there is a data race there. The value of a volatile can be changed by something outside the current thread. That’s what volatile means and why it exists. Edit: thread=thread of execution. I’m not making a point about thread safety within a program.

Can also represent a register that has an effect reading it. Reading a memory mapped register can have side effects. Like memory mapped io on a UART will fetch the next byte to be read.

Re: Everything in C is undefined behavior

#256

Earlier quoted context omitted.

C is not a simple language in the sense that writing software in C is simple, and I think that's the only useful way to understand the word "simple" in this context. Brainfuck is "simple" by any other definition as well, but that's not a useful quality.

C is a far simpler language than, for example, Swift. It's cognitive load in order to actually write something is pretty small - even the authors state that their book about C is intentionally slim because the concepts to understand are not that many. That doesn't mean the C is a safer language than Swift, or a less-capable language than Swift. But in terms of "easy to understand along the happy-path", it's a lot eas…

The point I'm getting at is that your definition of "simple" (a word that should be banned among programmers) is not useful, if it is even meaningful.

The brainfuck example is "simpler": Only 8 kinds of tokens! Not really useful, though.

The cognitive load of _actually delivering software_ written in C is immensely greater than doing so with Swift, or Rust, or Python, or Java, even Zig, despite all of those leveraging much heavier machinery in order to deliver a friendlier abstract model for you to program against.

The tragedy of C is that, in addition only delivering very baseline abstraction tools, it also adds its own set of seemingly arbitrary rules and requirements that come from nowhere but the C standard. Fictitious limitations to suit a bygone era. The abstract model of C is fine in some places, but definitely not fine in other places, and my hypothesis is that most UB in practice comes from a mismatch between programmer intuitions and C's idiosyncracies.

Re: Everything in C is undefined behavior

#257
post #104
post #79

Earlier quoted context omitted.

Ada 83 has no UB on call stack overflow, from the reference manual : http://archive.adaic.com/standards/83lrm/html/lrm-11-01.html "STORAGE_ERROR This exception is raised in any of the following situations: (...) or during the execution of a subprogram call, if storage is not sufficient."

So it's just as useful as when your stack area ends with a page that will segfault on access, or your CPU will raise an interrupt if stack pointer goes beyond a particular address? It's not safe though because throwing an exception, panicking, etc, is still a denial of service. It's just more deterministic than silently overwriting the heap instead. If the program is critical then you need to be able to statically pr…

A segfault is considered safe if you're talking about functional safety because it results in a return to a defined safe state (RTDSS).

If a segfault leads to some other state you do not deem "safe", such as a single program gating access to a valuable asset with a default fail state of "allow", you just have a fundamental design flaw in your system. The safety problem is you or your AI agent, not the segfault.

Re: Everything in C is undefined behavior

#258
post #231

Earlier quoted context omitted.

This is a description of an imaginary compiler, evoked by the ANSI/ISO standards documents, which has never existed and will never exist. To understand what the program will do, you just have to understand the compiler behavior on your target platforms. A helpful intuition pump is: imagine the ANSI/ISO specifications simply do not exist; now what? Well, you just continue your engineering practice, the way you would f…

> just That word is carrying a lot of weight here. Compilers are unbelievably complex these days, and it's impossible for any one human to fully understand the entire compilation process, including the effects of any arbitrary combination of compiler flags. Any assumptions you have about what the compiler does in the face of UB will collapse on the next patch release of that compiler, or the moment somebody changes t…

Yet the standard does not tell you what the compilers do.

Linux works on a wide variety of platforms. It also relies on those platforms behaving predictably with respect to what the standard leaves undefined.

This description of ISO UB as a totally insane wonderland of random, malevolent semantics just doesn't describe reality.

Re: Everything in C is undefined behavior

#259
post #253

Some of the C++ code in this article has not been idiomatic in over a decade, and would be considered a code smell today. The language has evolved into quite a different language than when it was first created. As soon as I saw all of those raw pointers and direct pointer access, it was clear that at least part of this article should be taken with a grain of salt. The other obvious issue with the overall perspective…

[deleted]

Re: Everything in C is undefined behavior

#260

I have never in my 20 years of writing C heard so much about undefined behavior as I have in the past 6 months on Hacker News. It has never entered the conversation. You write the code. If it doesn't work, you debug it and apply a fix or a workaround. Why does the idea of undefined behavior in C get to the front page so consistently?

After the rise of Rust, it has gained more visibility? But some people were interested in C in this way long ago too, I used to hang out in some godforsaken irc channel where people competed in out-pedanticing each other over the C standard.

I trust your historical C usage was more productive than that..

Post reply on HN