Questions tagged [strict-aliasing]

Strict aliasing is an assumption, made by the C or C++ compiler, that de-referencing pointers to objects of different types will never refer to the same memory location (i.e. they will not alias each other).

Strict aliasing is an assumption, made by the C or C++ compiler, that de-referencing pointers to objects of different types will never refer to the same memory location (i.e. they will not alias each other).

Strict aliasing or "the strict aliasing rule" are informal terms. It refers not to one, but to a set of rules regarding type compatibility when accessing a value through pointers.

A "strict aliasing violation" is when a value is accessed through a pointer which is not compatible with the data type. Example:

short array[2];
int* ptr = (int*)array;       // strict aliasing violation
if(*ptr == something)         // therefore, this is undefined behavior

Strict aliasing is explained in detail here: What is the strict aliasing rule?

The reason why the strict aliasing exists is performance, as discussed here. A compiler which assumes that the strict aliasing rule is followed can make various optimizations to increase performance.

Traditionally, not many compilers have done such optimizations, and therefore the undefined behavior caused by strict aliasing violations is a common dormant bug in many programs - a bug that will not surface until the program is ported to a compiler which uses such optimizations.

The GCC compiler in particular is known to frequently do such optimizations. They are automatically enabled with compiler options -O2, -O3 or -Os, or explicitly with -fstrict-aliasing. Strict aliasing optimizations can be disabled with -fno-strict-aliasing. GCC reference.


The aliasing rules are described in the following sections in the standards:

C11 6.5 §7

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
— a type compatible with the effective type of the object,
— a qualified version of a type compatible with the effective type of the object,
— a type that is the signed or unsigned type corresponding to the effective type of the object,
— a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
— an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
— a character type.

C++11 3.10 §10.

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:
— the dynamic type of the object,
— a cv-qualified version of the dynamic type of the object,
— a type similar (as defined in 4.4) to the dynamic type of the object,
— a type that is the signed or unsigned type corresponding to the dynamic type of the object,
— a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
— an aggregate or union type that includes one of the aforementioned types among its elements or nonstatic data members (including, recursively, an element or non-static data member of a subaggregate or contained union),
— a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
— a char or unsigned char type.

563 questions
9
votes
3 answers

Best practices for object oriented patterns with strict aliasing and strict alignment in C

I've been writing embedded C code for many years now, and the newer generations of compilers and optimizations have certainly gotten a lot better with respect to their ability to warn about questionable code. However, there is at least one (very…
Joe Hickey
  • 810
  • 7
  • 8
9
votes
2 answers

C - Conversion behavior between two pointers

Update 2020-12-11: Thanks @"Some programmer dude" for the suggestion in the comment. My underlying problem is that our team is implementing a dynamic type storage engine. We allocate multiple char array[PAGE_SIZE] buffers with 16-aligned to store…
Richard Bryant
  • 154
  • 2
  • 5
9
votes
1 answer

Strict aliasing rules broken with templates and inheritance

The following code gives me warning in gcc that I break strict aliasing rules: struct Base { int field = 2; }; template struct Specialization: public Base { void method() { Specialization copy; field = copy.field; …
S. Kaczor
  • 401
  • 3
  • 8
9
votes
1 answer

Is it well-defined to use memset on a dynamic bool array?

Is this code well-defined behavior, in terms of strict aliasing? _Bool* array = malloc(n); memset(array, 0xFF, n); _Bool x = array[0]; The rule of effective type has special cases for memcpy and memmove (C17 6.5 §6) but not for memset. My take is…
Lundin
  • 195,001
  • 40
  • 254
  • 396
9
votes
3 answers

Strict Aliasing Rule and Type Aliasing in C++

I am trying to get a grasp of undefined-behavior when violating the strict aliasing rule. I have read many articles on SO in order to understand it. However, one question remains: I do not really understand when two types illegaly alias.…
user4290866
9
votes
2 answers

Plain C polymorphism, type punning, and strict aliasing. How legal is this?

I've been trying to work out how legal the below is and I could really use some help. #include #include typedef struct foo { int foo; int bar; } foo; void make_foo(void * p) { foo * this = (foo *)p; this->foo…
9
votes
2 answers

Strict aliasing and overlay inheritance

Consider this code example: #include typedef struct A A; struct A { int x; int y; }; typedef struct B B; struct B { int x; int y; int z; }; int main() { B b = {1,2,3}; A *ap = (A*)&b; *ap = (A){100,200}; …
Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
9
votes
5 answers

Reinterpret struct with members of the same type as an array in a standard compliant way

In various 3d math codebases I sometimes encounter something like this: struct vec { float x, y, z; float& operator[](std::size_t i) { assert(i < 3); return (&x)[i]; } }; Which, AFAIK is illegal because…
9
votes
5 answers

Is unsigned char a[4][5]; a[1][7]; undefined behavior?

One of the examples of undefined behavior from the C standard reads (J.2): — An array subscript is out of range, even if an object is apparently accessible with the given subscript (as in the lvalue expression a[1][7] given the declaration int …
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
9
votes
3 answers

Is it possible to enable link-time optimization while only disabling strict aliasing for some functions?

My program conforms to the strict aliasing rule, except for one place: a compilation unit which contains hashing functions such as MurmurHash3, SpookyHash, etc. On x86 and x86_64, these hashing functions accept a const char *, cast them to uint32,…
Hongli
  • 18,682
  • 15
  • 79
  • 107
9
votes
1 answer

strict aliasing in C

Question about type punning: why does this code break strict aliasing rules: int main() { int a = 1; short j; printf("%i\n", j = *((short*)&a)); return 0; } and this is not: int main() { int a = 1; short j; int *p; …
user3506106
  • 141
  • 7
9
votes
4 answers

Does this pointer casting break strict aliasing rule?

This is the fast inverse square root implementation from Quake III Arena: float Q_rsqrt( float number ) { long i; float x2, y; const float threehalfs = 1.5F; x2 = number * 0.5F; y = number; i = * (…
Vilhelm Gray
  • 11,516
  • 10
  • 61
  • 114
8
votes
1 answer

Strict aliasing within an expression

Suppose we have the following code: #include #include int main() { uint16_t a[] = { 1, 2, 3, 4 }; const size_t n = sizeof(a) / sizeof(uint16_t); for (size_t i = 0; i < n; i++) { uint16_t *b = (uint16_t…
Pedro
  • 842
  • 6
  • 16
8
votes
2 answers

`u8string_view` into a `char` array without violating strict-aliasing?

Premise I have a blob of binary data in memory, represented as a char* (maybe read from a file, or transmitted over the network). I know that it contains a UTF8-encoded text field of a certain length at a certain offset. Question How can I (safely…
smls
  • 5,738
  • 24
  • 29
8
votes
3 answers

Calling FFTW's in-place real-to-complex transform without violating strict aliasing rules

I wish to call fftw's in-place real-to-complex transform function, which has the following signature: fftw_plan fftw_plan_dft_r2c_1d( int n, // transform length double* in, // pointer to input array fftw_complex* out,…
SumDood
  • 294
  • 1
  • 7