Live data from Hacker News

Everything in C is undefined behavior

blog.habets.se

281–290 of 748 posts

Re: Everything in C is undefined behavior

#281
post #181

Earlier quoted context omitted.

In many architectures does not mean you can. The standard is supposed to cover all architectures.

If some architecture traps on unaligned access, then the compiler can and should simply generate the correct code so that it loads the integer piece by piece instead. Load multiple integers and shift and mask away the irrelevant bits, done. This is exactly what modern architectures already do in hardware. Works, it's just a little slower. This is exactly what the compilers do if you use a packed structure to access u…

The pointer might be something you forced. The compiler needs to do the right thing but if you set the pointer to an unaligned address because you have information on the hardware you can get this undefined situation with nothing the compiler can do about it.

Re: Everything in C is undefined behavior

#282

Earlier quoted context omitted.

I would agree that C is "really flexible", but I would say it's primarily flexible because it lets you cast say from a void pointer to a typed pointer without requiring much boilerplate. It's also flexible because it lets you control memory layout and resource management patterns quite closely. If you want to be standards correct, yes you have to know the standard well. True. And you can always slip, and learn anothe…

It's not flexible in practice, because knowing the standard isn't optional. If you make the choice to not follow the standard, you're making the choice to write fundamentally broken software. Sometimes with catastrophic consequences.

I'm making the choice to pass pointers as void to get low-friction polymorphism. I'm making the choice to control the memory layout of my data structures, including of levels and type of indirection. I'm making the choice to control my own memory allocators and closely control lifetimes, closely control (almost) everything that happens in the system.

That has nothing to do with not following the standard.

Re: Everything in C is undefined behavior

#284

Earlier quoted context omitted.

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.

I would agree that C is "really flexible", but I would say it's primarily flexible because it lets you cast say from a void pointer to a typed pointer without requiring much boilerplate. It's also flexible because it lets you control memory layout and resource management patterns quite closely. If you want to be standards correct, yes you have to know the standard well. True. And you can always slip, and learn anothe…

The problem is that a lot of the flexibility introduced by UB doesn't serve the developer.

Take signed integer overflow, for example. Making it UB might've made sense in the 1970s when PDP-1 owners would've started a fight over having to do an expensive check on every single addition. But it's 2026 now. Everyone settled on two's complement, and with speculative execution the check is basically free anyways. Leaving it UB serves no practical purpose, other than letting the compiler developer skip having to add a check for obscure weird legacy architectures. Literally all it does is serve as a footgun allowing over-eager optimizations to blow up your program.

Although often a source of bugs, C's low-level memory management is indeed a great source of flexibility with lots of useful applications. It's all the other weird little UB things which are the problem. As the article title already states: writing C means you are constantly making use of UB without even realizing it - and that's a problem.

Re: Everything in C is undefined behavior

#285

Earlier quoted context omitted.

> They understand that all types "are" just bytes and that all pointers "are" just register-sized integer addresses, because that's how the hardware works and has worked for decades. I'd clarify this with "They understand that all values are just bytes" . > Meanwhile, the actual computers we have been using for decades have no problems actually just loading 4 bytes through any arbitrary pointer with zero overhead. It…

>It's partly the standards fault here - rather than saying "We don't know how vendors will implement this, so we shall leave it as implementation-defined", they say "We don't know how vendors will implement this, so we will leave it as undefined I'd agree to a point. I still think it's unreasonable for compiler writers to get all lawyery about precise terminology. After all "implementation defined" could still be sub…

This series was a good explanation for me of why treating UB this way is genuinely useful: https://blog.llvm.org/2011/05/what-every-c-programmer-should...

Being able to assume certain things don't happen is powerful when you're writing optimisations, not doing that would have a real performance cost

Re: Everything in C is undefined behavior

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

This has got nothing to do with data races etc. but everything to do with "Sequence Points and Single Update Rule" which is well described in C language specification.

See my comment here - https://news.ycombinator.com/item?id=48205760

Re: Everything in C is undefined behavior

#287

Earlier quoted context omitted.

There are still modern CPUs that don't support misaligned access. It would be insane for C to mandate that misaligned accesses are supported. However I do agree that just saying "the behaviour is undefined" is an unhelpful cop-out. They could easily say something like "non-atomic misaligned accesses either succeed or trap" or something like that. > In the end it's the CPU and not the compiler which decides whether an…

> They could easily say something like "non-atomic misaligned accesses either succeed or trap" or something like that. That means that the compiler must emit the read, even if the value is already known or never used, as it might trap. There is a reason for the UB!

No it doesn't. Compilers are only required to emit the read for volatile types. If the type is non-volatile, misaligned, and can be optimised out then it would be perfectly fine to omit it (that would be the "succeed" option).

Re: Everything in C is undefined behavior

#288

Earlier quoted context omitted.

One example along this path as an example is that every function must either terminate or have a side effect. I don't think one has bitten me yet but I could completely see how you accidentally write some kind of infinite loop or recursion and the function gets deleted. Also, bonus points for tail recursion so this bug might only show up with a higher optimization level if during debug nothing hit the infinite loop.

Infinite loop without side effects == program stuck and not responding on user input and not outputting anything. That's not something a useful program will ever want to do.

[deleted]

Re: Everything in C is undefined behavior

#290

Earlier quoted context omitted.

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.

C23 removed the whole stuff about indeterminate value and trap representation. Underflow/overflow being silent or not is implementation defined.
Post reply on HN