Live data from Hacker News

GCC always assumes aligned pointer accesses (2020)

trust-in-soft.com

81–90 of 128 posts

Re: GCC always assumes aligned pointer accesses (2020)

#81
post #2

The arguments in this blogpost are fundamentally flawed. The fact that they opened a bug based on them but got shut down should have raised all red flags. When compiling and running a C program, the only thing that matters is "what the C abstract machine does". Programs that exhibit UB in the abstract machine are allowed to do "anything". Trying to scope that down using arguments of the form "but what the hardware do…

Great, except no implementation of the C abstract machine actually exists. So you can't test against it. All you have are compilers that use it to justify miscompiling your code. We need a C interpreter that intentionally implements C machine features that don't correspond to any architectural feature - i.e. pointers are (allocation provenance, offset) pairs, integer overflow panics, every pointer construction is che…

The blog post company does sell a C interpreter that checks for all undefined behaviors (with provenance and offset).

Re: GCC always assumes aligned pointer accesses (2020)

#82
post #2

The arguments in this blogpost are fundamentally flawed. The fact that they opened a bug based on them but got shut down should have raised all red flags. When compiling and running a C program, the only thing that matters is "what the C abstract machine does". Programs that exhibit UB in the abstract machine are allowed to do "anything". Trying to scope that down using arguments of the form "but what the hardware do…

I think it is a good blog post, because it highlights an issue that I was not aware of and that I think many programmers are not. I do think I am a decent C programmer, and I spotted the strict aliasing issue immediately, but I didn't know that unaligned pointer access is UB. Because let's face it, the majority of programmers didn't read the standard, and those who did don't remember all facets.

I first learned many years ago that you should pick apart binary data by casting structs, using pointers to the middle of fields and so on. It was ubiquitous for both speed and convenience. I don't know if it was legal even in the 90s, but it was general practice - MS Office file formats from that time were just dumped structs. Then at some point I learned about pointer alignment - but it was always framed due to performance, and due to the capabilities of exotic platforms, never as a correctness issue. But it's not just important to learn what to do, but also why to do it, which is why we need more articles highlighting these issues.

(And I have to admit, I am one of these misguided people who would love a flag to turn C into "portable assembler" again. Even if it is 10x slower, and even if I had to add annotations to every damn for loop to tell the compiler that I'm not overflowing. There are just cases where understanding what you are actually doing to the hardware trumps performance.)

Re: GCC always assumes aligned pointer accesses (2020)

#83

Earlier quoted context omitted.

The blog post is also kind of unhinged because in the incredibly rare cases where you would want to write code like this you can literally just use the asm keyword. I think it's also worth considering WHY compilers (and the C standard) make these kinds of assumptions. For starters, not all hardware platforms allow unaligned accesses at all. Even on x86 where it's supported, you want to avoid doing unaligned reads at…

While the sentiment is correct as to why compilers makes alignment assumptions, a lot of the details here I think are not quite right. > For starters, not all hardware platforms allow unaligned accesses at all If you're dealing with very simple CPUs like the ARM M0, sure. But even the M3/M4 allows unaligned access. > Even on x86 where it's supported, you want to avoid doing unaligned reads at all costs because they'r…

> If you're dealing with very simple CPUs like the > ARM M0, sure. But even the M3/M4 allows unaligned > access.

On ARM M3/M4 you have the same issue with LDRD and STRD instructions which do not allow unaligned access. Even the normal load/stores don't allow unaligned access in all cases. Try this in the peripheral memory region for starters. And things get even more complicated when the memory protection unit shakes up things.

Re: GCC always assumes aligned pointer accesses (2020)

#84

Earlier quoted context omitted.

If a --k&r mode were to be reliable, wouldn't it need to get specified first? Otherwise people would start relying on some edge case. If speed is not a requirement for the --k&r mode, you could just take the tis-interpreter and note that if it runs without UB, it is still much faster than an actual computer was when k&r were active. Would it even be possible to specify a variant of C that contains no UB (e.g. would d…

It could probably only be used with a neural link. It would read your mind, then emit code that matches your perception of what you imagine old compilers did.

You jest, but there was some real effort put in to attempt define a dialect of C that would be less UB etc. And indeed the big problem was defining the semantics:

> After publishing the Friendly C Proposal, I spent some time discussing its design with people, and eventually I came to the depressing conclusion that there’s no way to get a group of C experts — even if they are knowledgable, intelligent, and otherwise reasonable — to agree on the Friendly C dialect. There are just too many variations, each with its own set of performance tradeoffs, for consensus to be possible.

https://blog.regehr.org/archives/1287

Re: GCC always assumes aligned pointer accesses (2020)

#85

Storing pointers unaligned and using memcpy to extract them to an aligned pointer, can be a performance gain, if it means less padding taking up valuable cache space.

In the right circumstances, you're very right -- but most people will get some aspect of this wrong.

Re: GCC always assumes aligned pointer accesses (2020)

#86
post #26

In a project I'm working on[0], there's an array object type used throughout, which can sometimes point to arbitrary data elsewhere. In a funky edge-case[1], such an array can be built with an unaligned data pointer. Thus, if gcc/clang started seriously utilizing aligned pointer accesses everywhere, nearly every single load & store in the entire project would have to be replaced with something significantly more verb…

> This leads to a problem when e.g. taking i8 elements [3;7) and reinterpreting as an i32 array.

Even ignoring alignment issues, this is already UB because it violates the strict aliasing rule. You technically need to memcpy and hope that the compiler optimizes the memcpy out. In C++20 you can use std::bit_cast in some circumstances. https://en.cppreference.com/w/cpp/numeric/bit_cast. In C11 you can use a union, but that still requires a "copy" into the union.

Re: GCC always assumes aligned pointer accesses (2020)

#87
post #2

The arguments in this blogpost are fundamentally flawed. The fact that they opened a bug based on them but got shut down should have raised all red flags. When compiling and running a C program, the only thing that matters is "what the C abstract machine does". Programs that exhibit UB in the abstract machine are allowed to do "anything". Trying to scope that down using arguments of the form "but what the hardware do…

Great, except no implementation of the C abstract machine actually exists. So you can't test against it. All you have are compilers that use it to justify miscompiling your code. We need a C interpreter that intentionally implements C machine features that don't correspond to any architectural feature - i.e. pointers are (allocation provenance, offset) pairs, integer overflow panics, every pointer construction is che…

UBSan covers each of those except provenance checking, and ASan mostly catches provenance problems even though that's not directly the goal. There are some dumb forms of UB not caught by any of the sanitizers, but most of them are.

Making your program UBSan-clean is the bare minimum you should do if you're writing C or C++ in 2023, not an absurd goal. I know it'll never happen, but I'm increasingly of the opinion that UBSan should be enabled by default.

Re: GCC always assumes aligned pointer accesses (2020)

#88
post #26

In a project I'm working on[0], there's an array object type used throughout, which can sometimes point to arbitrary data elsewhere. In a funky edge-case[1], such an array can be built with an unaligned data pointer. Thus, if gcc/clang started seriously utilizing aligned pointer accesses everywhere, nearly every single load & store in the entire project would have to be replaced with something significantly more verb…

> This leads to a problem when e.g. taking i8 elements [3;7) and reinterpreting as an i32 array. Even ignoring alignment issues, this is already UB because it violates the strict aliasing rule. You technically need to memcpy and hope that the compiler optimizes the memcpy out. In C++20 you can use std::bit_cast in some circumstances. https://en.cppreference.com/w/cpp/numeric/bit_cast . In C11 you can use a union, but…

I'm of course already using -fno-strict-aliasing (primarily because without it it's impossible to implement a custom memory allocator, but it also helps here).

Re: GCC always assumes aligned pointer accesses (2020)

#89
post #19

Earlier quoted context omitted.

I would argue it's the modern understanding of C standard is flawed. Back in 89, many of those unspecified behavior were understood as implementation/hardware dependent, not undefined. Aliasing was the norm, `restrict` was actually a keyword. Modern C is neither safe nor low-level.

I haven't gotten to use C in industry, but I was taught that undefined behavior just means that it is defined by the running system and not the compiler. Is that not the general understanding? Maybe I was just taught that way because it was old timers teaching it.

If the language standard leaves some behavior undefined, other sources (e.g., POSIX, your ABI, your standard library docs, or your compiler docs) are free to define it. If they do, and you are willing to limit your program’s portability, you can use that behavior with confidence. But they also leave many behaviors undefined, and you can’t rely on those.

For implementation-defined behavior, the language standard lays out a menu of options and your implementation is required to pick one and document it. IMHO, many things in the C standard are undefined that ought to be implementation-defined. But unaligned pointer accesses would be hard to handle that way; at best you could make the compiler explicitly document whether or not it supports them on a given architecture.

Post reply on HN