The example of bad gcc behavior was essentially type punning, which is well-known to cause trouble. Is there an example where things break on misaligned access to non-overlapping objects?
Misaligned accesses, in general, without any qualification, can earn you a SIGSEGV or SIGBUS. It's mostly x86 that's being very tolerant here; other architectures are much less forgiving to varying degrees. That's also why this rule is in the C standard to begin with. Misaligned accesses need different / multiple instructions on some of these architectures, making them significantly more expensive. So the decision wa…
GCC always assumes aligned pointer accesses
51–60 of 93 posts
Re: GCC always assumes aligned pointer accesses
#52Earlier quoted context omitted.
Indeed, PDP/11s don't like it. Older ARM designs too, though I believe they allow it since about ARM6 (perhaqps because x86 does?).
The arms allow it since ARMv5, but it's still not quite what one would expect until ARMv7. However it has a significant performance penalty when doing it. https://medium.com/@iLevex/the-curious-case-of-unaligned-acc...
Re: GCC always assumes aligned pointer accesses
#53Earlier quoted context omitted.
Basically yeah, but it gets much more complicated. For example, when a write hits memory is actually not the same thing as when it's observable by some particular other processor. There might be particular rules for writes that have dependencies too. Here's some good reading material if you have a spare afternoon. https://www.kernel.org/doc/Documentation/memory-barriers.txt Amusingly, it treats dependency issues as o…
The modern thing is using acquire/release semantics on the variables you actually care about intra-thread ordering on, rather than full barriers, which impose a higher cost.
Re: GCC always assumes aligned pointer accesses
#54No. [as in: this isn't about GCC.] The C standard requires that pointers generally be created from referencing a valid, existing object. A misaligned integer is not a valid "object", thus the compiler may assume that all pointers to ints are aligned (to 4 bytes.) https://en.cppreference.com/w/cpp/language/pointer Every value of pointer type is one of the following: - a pointer to an object or function (in which case…
>> The C standard requires that pointers generally be created from referencing a valid, existing object. It is common to reference memory mapped peripherals by casting an integer to a struct pointer. In that case only a human can certify the validity of the object.
Re: GCC always assumes aligned pointer accesses
#55Few seem to know x86 can generate misaligned access exception. Enabling EFLAGS Alignment Check (bit 18) flag causes an exception on any misaligned access, if the kernel has enabled this feature by setting CR0 register Alignment Mask (bit 18).
You do not need to enable anything. SSE instructions require aligned access, and will crash if used with wrong alignment, irrespective of the flag.
Nothing in the OpenGL specs says the buffers passed to it (think it was glBufferData) has to be 16byte aligned, but with NVIDIA it would crash with an alignment exception if they were not. The memory allocater in the language I used, Delphi, only used 4 byte alignment (32bit).
They might have fixed this, this was well over a decade ago.
Re: GCC always assumes aligned pointer accesses
#56Earlier quoted context omitted.
Why "no", you're agreeing with the conclusion
Sort of. He definitely talks about the fact that it is undefined behaviour to create a misaligned pointer: > Strictly speaking, the function f invokes Undefined Behavior when it computes [the misaligned pointer] But he thinks it is still a problem with GCC, in that GCC should not be allowed to take advantage of this particular UB. He explains his view much better in the bug report: > GCC assumes that pointers must be…
I am not saying or thinking that there is a problem with GCC. I do think that GCC and Clang would be more useful with an option to make them not assume that every pointer is aligned if the target architecture does not impose this, but that's not the same thing as saying there is something wrong with GCC.
The message of the post, rather than “something is wrong with GCC”, is, “Beware. You might think that this is okay to do in your C programs, but it is not and here is why.”
Also before I post something like this, I need a confirmation that the behavior is intended and not accidental. It has happened to me before that I was about to document that GCC had an agressive behavior with respect to a kind of optimization (while remaining arguably in line with the intent of the standard, even if the word of the standard was in this case ambiguous enough to be interpreted any which way), and my co-author and I had to use a “missed optimization” ticket on GCC's bugzilla in order to have them confirm that GCC was doing the thing in question on purpose. GCC's developers, seeing the bug report, changed the behavior to remove the optimization entirely instead: https://gcc.gnu.org/ml/gcc/2016-11/msg00111.html
Coming back to the example at hand, if I had phrased the ticket as “GCC shouldn't optimize this”, it would have been closed instantly as “well it's UB”. I hoped for a more interesting search for a trade-off that would satisfy everyone, from people who just want legacy C code to keep working with new compilers to people who want programs to run as fast as possible if I phrased it this way.
(And yes, you have to ask in the bugzilla if you need some sort of official answer for this kind of thing. If you ask on a mailing list, you'll get a “no that was UB from the start” answer from someone you have never heard of who is in fact a power user who subscribed to the mailing list, and whose opinion, while useful, should not be assumed to be that of the compiler developers.)
Re: GCC always assumes aligned pointer accesses
#57The complaint isn't about alignment at all, it's that the optimizer assumes that two pointers to the same basic type cannot overlap in memory. The generated code is correct except for the fact that the two arguments are distinct pointers to the same three bytes in memory. I believe this behavior is actually specified in the standard, actually, in the same section that defines the aliasing rules.
Plus on a some 32-bit ISA, a long long and a double only need to be aligned to 32-bit boundaries, so I note that in the made-up C rules that you are referring to, “basic type” is not very well defined.
> I believe this behavior is actually specified in the standard, actually,
> in the same section that defines the aliasing rules.
The strict aliasing rules are here: https://port70.net/~nsz/c/c11/n1570.html#6.5p7
Go ahead and point to the rule that says that “basic types” cannot overlap with themselves.
Re: GCC always assumes aligned pointer accesses
#58The complaint isn't about alignment at all, it's that the optimizer assumes that two pointers to the same basic type cannot overlap in memory. The generated code is correct except for the fact that the two arguments are distinct pointers to the same three bytes in memory. I believe this behavior is actually specified in the standard, actually, in the same section that defines the aliasing rules.
Yes, this is the compiler optimizing UB due to aliasing , not due to alignment.
I make sense of the C standard for a living (this is literally my day job) and I do not see what clause of the C standard you are referring to. It would be very useful to me to know which clause you are referring to, and I would be eternally thankful.
Re: GCC always assumes aligned pointer accesses
#59This isn't just an issue with GCC but embedded compilers as well. On embedded systems its common to work with packed data structures to maximize serial protocol efficiency. Lets say you have a packed structure with a type of struct MyPackedStruct { uint8_t byteValue; uint32_t intValues[5]; } Normally a compiler would add 3 extra bytes between the uint8_t value and the uint32_t array to keep alignment of the int array…
uint32_t [[aligned(1)]]*intValues = myPackedStruct.intValues;
Would be nice if we also got e.g. float/intNua_t for unaligned types. Any code that gets broken by this change was broken to begin with.Re: GCC always assumes aligned pointer accesses
#60Earlier quoted context omitted.
>> The C standard requires that pointers generally be created from referencing a valid, existing object. It is common to reference memory mapped peripherals by casting an integer to a struct pointer. In that case only a human can certify the validity of the object.
The C language does not support what you're trying to do. You should use assembly to do this.