Live data from Hacker News

GCC always assumes aligned pointer accesses (2020)

trust-in-soft.com

111–120 of 128 posts

Re: GCC always assumes aligned pointer accesses (2020)

#111
post #76

The D programming language does not allow the creation of misaligned pointers in code marked as @safe, and in @safe code assumes they are aligned. In @system code you can do whatever you like, but things need to be aligned that are provided to @safe code.

Doesn't look like that changes anything about actual dereferencing though, which is the primary thing discussed - https://godbolt.org/z/4vW5Ksnab still emits an "align 4", which llvm could still assume as UB if violated (though I don't know if it ever does).

@safe code prevents unaligned references from being generated, so it can assume the references are aligned.

Re: GCC always assumes aligned pointer accesses (2020)

#112
post #23

Earlier quoted context omitted.

Honestly, I think you are both incorrect. C has always had a concept of implementation defined behavior, and unaligned memory accesses used to be defined to work correctly on x86. Intel added instructions that can’t handle unaligned access, so they broke that contract. I’d argue that it is an instruction set architecture bug. Alternatively, Intel could argue that compilers shouldn’t emit vector instructions unless th…

Loads of architectures can't do misaligned memory access. Even x86 has problems when variables span cache lines. The compiler usually deals with this for the programmer, e.g. by rounding the address down then doing multiple operations and splicing the result together.

Most modern architectures that target high performance implementations can do unaligned accesses, even ones crossing page boundaries.

Less common is support for atomic RMW access to unaligned location. x86 does support it but crossing a cache line causes the operation to be very slow.

Re: GCC always assumes aligned pointer accesses (2020)

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

> 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.

All C compilers implement the C abstract machine. It is not used to justify miscompiling code, it is used to specify behavior of compiled code.

> We need a C interpreter

Interpreter or not is not relevant, there must be some misconception. Any behavior you can implement with an interpreter can be implemented with compiled code. E.g., add a test and branch after each integer operation if you want to crash on overflow.

> 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 checked, etc.

As others have mentioned there are static and dynamic checkers (sanitizers) that test for such things nowadays. In compiled, not interpreted code, mind you.

> If only to point out how hilariously absurd the ISO C UB rules are and how nobody actually follows them.

It's not that bad.

> My personal opinion is that "undefined behavior" was a spec writing mistake that has been rules-lawyered into absurdity. For example, signed integer overflow being UB was intended to allow compiling C to non-twos-compliment machines. This was interpreted to allow inventing new misbehaviors for integer overflow instead of "do whatever the target architecture does."

The spec uses implementation defined behavior for that. Although you can argue that they went the wrong way on some choices -- signed integer overflow "depends on the machine at hand" in the first K&R, which you could say would be reasonable to call it implementation specific and enumerate the behaviors of supported machines.

C had a long history with hardware manufacturers, compiler writers, and software developers though, so the standard can never universally please everybody. The purpose of standardization was never to make something that was easiset for software development, ignoring the other considerations. So a decision is not an example of design by committee gone wrong just because happened to be worse for software writers (e.g., choosing to make overflow undefined instead of implementation dependent). You would have to know why such a decision was made.

Re: GCC always assumes aligned pointer accesses (2020)

#114

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…

> Even on x86 where it's supported, you want to avoid doing unaligned reads at all costs because they're up to 2x slower than aligned accesses. This is generally not true.

It is generally true because "up to" includes the same speed. However, unaligned memory can significantly impact caching.

Re: GCC always assumes aligned pointer accesses (2020)

#115

Earlier quoted context omitted.

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 general problem with this argument is that “do what the hardware does” is actually not easy to reason about. The end results of this typically are impossible to grok.

Not if possible implementations are specified, and especially if you can target machines of particular behavior. Which is of course how you can write endian and bit size portable code.

Re: GCC always assumes aligned pointer accesses (2020)

#116

Earlier quoted context omitted.

What you are talking about is implementation-defined behavior. It exists in the C standard separately from the undefined behavior.

Implementation Defined behavior means the standards authors provided a list of possible behaviors, and compiler authors must pick one and document which they picked. Unspecified behavior is more what you're thinking of, though in that case the standard still provides a list of possibilities that compiler authors have to pick from, they just don't have to document it or always make the same choice for every program. T…

> Implementation Defined behavior means the standards authors provided a list of possible behaviors

The standard definitely does not require implementations to pick from a list of possible behaviors. All the standard requires is that the implementation document the behavior.

For example, the behavior on integer demotion is implementation-defined and there's no list of possible behaviors:

> When an integer is demoted to a signed integer with smaller size, or an unsigned integer is converted to its corresponding signed integer, if the value cannot be represented the result is implementation-defined.

> Unspecified behavior is more what you're thinking of, though in that case the standard still provides a list of possibilities that compiler authors have to pick from

That contradicts the standard's definition of unspecified behavior. For example, from the C89 draft (emphasis added) [0]:

> Unspecified behavior --- behavior, for a correct program construct and correct data, for which the Standard imposes no requirements.

[0]: https://port70.net/%7Ensz/c/c89/c89-draft.html#1.6sd

Re: GCC always assumes aligned pointer accesses (2020)

#117

Earlier quoted context omitted.

It dates to the first standardization of C in 1989. The "C as portable assembly" view ended when ANSI C got standardized, and K&R's 2nd edition was published.

For C to be portable this needs to be undefined behaviour because there are CPUs that don’t support unaligned access

It doesn't need to be undefined to say it crashes on some architectures.

Re: GCC always assumes aligned pointer accesses (2020)

#118

Earlier quoted context omitted.

For C to be portable this needs to be undefined behaviour because there are CPUs that don’t support unaligned access

It doesn't need to be undefined to say it crashes on some architectures.

I guess it could also be implementation defined

My point here is that you can’t have “everything works as it does in the native assembly language” and “portable assembly” at the same time because if you rely on implementation defined or undefined behaviour then it’s not portable any more

Re: GCC always assumes aligned pointer accesses (2020)

#119
post #4
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…

This line in particular really bugs me: > The present blog post brings bad, and as far as I know, previously undocumented news. Even if you really are targeting an instruction set without any memory access instruction that requires alignment, GCC still applies some sophisticated optimizations that assume aligned pointers. I could have told you this was true ~20 years ago, and the main reason I'm so conservative in ho…

27 years ago I was helping someone rearrange structs because word-sized fields were being word aligned, and you would waste a good deal of memory if you arranged by concept instead of for byte packing. I believe that was under Microsoft’s compiler.

Re: GCC always assumes aligned pointer accesses (2020)

#120

Earlier quoted context omitted.

It doesn't need to be undefined to say it crashes on some architectures.

I guess it could also be implementation defined My point here is that you can’t have “everything works as it does in the native assembly language” and “portable assembly” at the same time because if you rely on implementation defined or undefined behaviour then it’s not portable any more

That depends on what you mean by "portable". I think being able to use the same code across many platforms is enough to qualify. Being able to access raw machine behavior is part of the premise of portable assembly, not a disqualifier.
Post reply on HN