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
11
votes
2 answers

Does reinterpret_casting std::aligned_storage* to T* without std::launder violate strict-aliasing rules?

The following example comes from std::aligned_storage page of cppreference.com: #include #include #include template class static_vector { // properly aligned uninitialized storage for N…
xskxzr
  • 12,442
  • 12
  • 37
  • 77
11
votes
2 answers

What is the no-undefined-behavior way of deserializing an object from a byte array in C++11 (or later)?

To overcome alignment issues, I need to memcpy into a temporary. What type should that temporary be? gcc complains that the following reinterpret_cast will break strict aliasing rules: template T deserialize(char *ptr) { …
Martin C. Martin
  • 3,565
  • 3
  • 29
  • 36
11
votes
3 answers

Is it legal to alias a char array through a pointer to int?

I know that the following is explicitly allowed in the standard: int n = 0; char *ptr = (char *) &n; cout << *ptr; What about this? alignas(int) char storage[sizeof(int)]; int *ptr = (int *) &storage[0]; *ptr = 0; cout << *ptr; Essentially, I'm…
chbaker0
  • 1,758
  • 2
  • 13
  • 27
11
votes
3 answers

Can a std::array alias a fragment of a larger array?

Suppose we have a pointer T* ptr; and ptr, ptr+1, … ptr+(n-1) all refer to valid objects of type T. Is it possible to access them as if they were an STL array? Or does the following code: std::array* ay = (std::array*) ptr invoke…
kinokijuf
  • 968
  • 1
  • 11
  • 33
11
votes
3 answers

Does accessing array of POD struct as array of its single member violate strict aliasing?

I have integer values that are used to access data in unrelated data stores, i.e., handles. I have chosen to wrap the integers in a struct in order to have strongly typed objects so that the different integers cannot be mixed up. They are, and must…
rasmus
  • 3,136
  • 17
  • 22
11
votes
4 answers

Type punning a struct in C and C++ via a union

I've compiled this in gcc and g++ with pedantic and I don't get a warning in either one: #include #include #include struct a { struct a *next; int i; }; struct b { struct b *next; int i; }; struct c…
loop
  • 3,460
  • 5
  • 34
  • 57
11
votes
3 answers

Aliasing Arrays through structs

I'm reading paragraph 7 of 6.5 in ISO/IEC 9899:TC2. It condones lvalue access to an object through: an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate…
Persixty
  • 8,165
  • 2
  • 13
  • 35
11
votes
6 answers

Writing memcpy conformant with strict aliasing

The general answer when asking "how does one implement memcpy function conformant with strict aliasing rules" is something along the lines of void *memcpy(void *dest, const void *src, size_t n) { for (size_t i = 0; i < n; i++) …
Oleg Andreev
  • 353
  • 1
  • 9
11
votes
1 answer

Is this strict aliasing example correct?

I've been reading up on the strict aliasing rules over the last week or so and ran into this article: Understanding C/C++ Strict Aliasing. The article goes through several ways two swap the halves of a 32-bit integer, giving both good examples and…
zmb
  • 7,605
  • 4
  • 40
  • 55
11
votes
5 answers

How to cast the address of a pointer generically while conforming to the C standard

It is common to assign pointers with allocations using an implicit function-return void * conversion, just like malloc()'s: void *malloc(size_t size); int *pi = malloc(sizeof *pi); I would like to perform the same assignment while passing the…
Dror K.
  • 1,989
  • 17
  • 26
11
votes
1 answer

Generic char[] based storage and avoiding strict-aliasing related UB

I'm trying to build a class template that packs a bunch of types in a suitably large char array, and allows access to the data as individual correctly typed references. Now, according to the standard this can lead to strict-aliasing violation, and…
mitchnull
  • 6,161
  • 2
  • 31
  • 23
10
votes
4 answers

Is this hack to remove aliasing warning UB?

We just upgraded our compiler to gcc 4.6 and now we get some of these warnings. At the moment our codebase is not in a state to be compiled with c++0x and anyway, we don't want to run this in prod (at least not yet) - so I needed a fix to remove…
Nim
  • 33,299
  • 2
  • 62
  • 101
10
votes
1 answer

On the term "(strict) aliasing violation" relating to class member access

This question refers to the current C++20 draft. The quoted passages have been slightly modified from previous standard iterations, but not in relevant ways as far as I know. I am looking for clarification on the the terms "aliasing violation" or…
walnut
  • 21,629
  • 4
  • 23
  • 59
10
votes
1 answer

Which of these pointer comparisons should a conforming compiler be able to optimize to "always false"?

In an attempt to get a better understand of how pointer aliasing invariants manifested during optimization, I plugged some code into the renowned Compiler Explorer, which I'll repeat here: #include bool a(int *foo, int *bar) { (void)…
lcmylin
  • 2,552
  • 2
  • 19
  • 31
10
votes
2 answers

Aliasing array with pointer-to-struct without violating the standard

Reading this I understood that you can alias structures (without violating the standard, that is) if they have compatible members, i.e given the following struct: typedef struct { uint32_t a; uint32_t b; } Frizzly; The following would break…