3 ms·
> On a platform that doesn't have alignment requirements, it's not a bug to access misaligned data Consider the following statement: > On a platform that has
by sjolsen 12y ago
> On a platform that doesn't have alignment requirements, it's not a bug to access misaligned data
Consider the following statement:
> On a platform that has well-defined signed overflow, it's not a bug to perform signed overflow.
If you've ever cranked up GCC's optimization settings on a program that performs signed overflow, you know this simply isn't true.
In general, the fact that the underlying hardware supports a certain set of machine semantics does not guarantee that the implementation will extend the semantics of the C or C++ abstract machine to match. It of course may do so—after all, it may do whatever it pleases once your program exhibits undefined behaviour—but unless you are specifically targeting your implementation's C- or C++-like dialect instead of ISO C or C++, accessing unaligned memory is a bug.
> Ubsan should adopt a couple of other safety improvements from C++
I agree that these should be adopted, but disagree that it should be ubsan which does so. These are statically detectable errors, so it should be the compiler which implements the detection, be it as a QOI extension or as part of the language standard.
- nkurz 12y ago> unless you are specifically targeting your implementation's > C- or C++-like dialect instead of ISO C or C++, accessing > unaligned memory is a bug. I'm ignorant. What exactly are the standard-defined C language requirements for alignment? I'd presumed the standard only defined relative alignments, and absolute alignment was only required by the implementation and hardware. But I'm not familiar with the spec. Is reading a 4-byte int from a non-multiple-of-four address explicitly undefined behavior?
- cygx 12y agoSpecific alignment requirements are up to the implementation. Nevertheless, the standard can (and does) specify that violating them is UB.
- sjolsen 12y ago> Is reading a 4-byte int from a non-multiple-of-four address explicitly undefined behavior? A type in C or C++ has an alignment, queryable through C's _Alignof and C++'s alignof. This is not necessarily the same as its size, though there is a relationship. Given a pointer-to-cv-T, you may only access memory through that pointer if the address it encodes is aligned to "_Alignof(cv-T)"/"alignof(cv-T)". If it is not appropriately aligned, accessing memory through it is undefined behaviour. In other words, the standards do not specify the alignment of any type (except to say that it's always at least 1, IIRC), but they do require that you respect alignments.
- nkurz 12y agoInteresting, thanks. I've recently been working on various optimizations that involve writing 32-bit integers with unaligned 128-bit vector writes, where I advance the pointer by a multiple of 4 (but not of 16) between writes, thus overwriting the tail of the previous write. Your explanation would seem to imply that there is no possible way this can be "spec correct". Since I need intrinsics and inline assembly for this anyway, strict spec adherence isn't a priority, but it's nice to learn more.
- dietrichepp 12y agoI'm wondering why you wouldn't use intrinsics to begin with, since most architectures have multiple load/store operations for vector types and using intrinsics you get to specify which load/store operation you use.
- nkurz 12y agoIn the case I'm speaking of, I can often handle the vector writes with intrinsics --- GCC, CLang, and ICC will accept unaligned pointers without problem. But the reason I'm using this write strategy (advancing output by a variable) is to avoid branch prediction errors by converting a jump table to a conditional move. Often (half the time?) I can't figure out a way to get the intrinsics to produce the assembly I want, much less across all three of those compilers. Combining the intrinsics with the conditional moves is what requires the inline assembly. Other places this comes up are addressing modes, operands that work directly on memory, and register allocation. For example, Haswell is capable of doing 2 loads and a store in a single cycle, but only if the store address is a "simple" base plus offset (no indexing). Convincing a compiler to produce a particular addressing mode is somewhat like teaching a blind person to drive a stick shift while you too are wearing a blindfold. Particularly if you are optimizing for a particular processor (and don't need to support Windows), inline assembly is considerably more reliable than depending on a compiler to consistently generate sane code.