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
25
votes
3 answers

Is it a strict aliasing violation to alias a struct as its first member?

Sample code: struct S { int x; }; int func() { S s{2}; return (int &)s; // Equivalent to *reinterpret_cast(&s) } I believe this is common and considered acceptable. The standard does guarantee that there is no initial padding…
M.M
  • 138,810
  • 21
  • 208
  • 365
25
votes
1 answer

Providing a C API to your C++ library and strict aliasing

A common pattern when providing a C API is to forward declare some opaque types in your public header which are passed to your API methods and then reinterpret_cast them into your defined C++ types once inside the translation unit (and therefore…
Sam Kellett
  • 1,277
  • 12
  • 33
25
votes
2 answers

will casting around sockaddr_storage and sockaddr_in break strict aliasing

Following my previous question, I'm really curious about this code - case AF_INET: { struct sockaddr_in * tmp = reinterpret_cast (&addrStruct); tmp->sin_family = AF_INET; tmp->sin_port =…
Abhinav Gauniyal
  • 7,034
  • 7
  • 50
  • 93
25
votes
5 answers

Can C's restrict keyword be emulated using strict aliasing in C++?

The Problem The restrict keyword in C is missing in C++, so out of interest I was looking for a way to emulate the same feature in C++. Specifically, I would like the following to be equivalent: // C void func(S *restrict a, S *restrict b) //…
PBS
  • 1,389
  • 11
  • 20
24
votes
3 answers

Examples using reinterpret_cast that do not trigger UB

Reading https://en.cppreference.com/w/cpp/language/reinterpret_cast I wonder what are use-cases of reinterpret_cast that are not UB and are used in practice? The above description contains many cases where it is legal to convert a pointer to some…
wimalopaan
  • 4,838
  • 1
  • 21
  • 39
24
votes
1 answer

What is the effective type of an object written by memset?

Code 1: unsigned int *p = malloc(sizeof *p); memset(p, 0x55, sizeof *p); unsigned int u = *p; Code 2: void *d = malloc(50); *(double *)d = 1.23; memset(d, 0x55, 50); unsigned int u = *(unsigned int *)d; In each case, what effect does memset have…
M.M
  • 138,810
  • 21
  • 208
  • 365
23
votes
4 answers

float bits and strict aliasing

I am trying to extract the bits from a float without invoking undefined behavior. Here is my first attempt: unsigned foo(float x) { unsigned* u = (unsigned*)&x; return *u; } As I understand it, this is not guaranteed to work due to strict…
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
23
votes
1 answer

Type punning with void * without breaking the strict aliasing rule in C99

I recently came across the strict aliasing rule, but I'm having trouble understanding how to use void * to perform type punning without breaking the rule. I know this breaks the rule: int x = 0xDEADBEEF; short *y = (short *)&x; *y = 42; int z =…
Vilhelm Gray
  • 11,516
  • 10
  • 61
  • 114
22
votes
5 answers

Does C strict aliasing make untyped static memory pools impossible?

WG14 member Jens Gustedt says in a blog post on strict aliasing rules: Character arrays must not be reinterpreted as objects of other types. Is that, in fact, true? (I guess the corresponding language in the standard is the part saying that if an…
20
votes
4 answers

strict aliasing and alignment

I need a safe way to alias between arbitrary POD types, conforming to ISO-C++11 explicitly considering 3.10/10 and 3.11 of n3242 or later. There are a lot of questions about strict aliasing here, most of them regarding C and not C++. I found a…
cooky451
  • 3,460
  • 1
  • 21
  • 39
20
votes
2 answers

Performance benefits of strict aliasing

In C, what exactly are the performance benefits that come with observing strict aliasing?
None
20
votes
2 answers

Undefined behavior on reading object using non-character type when last written using character type

Assuming unsigned int has no trap representations, do either or both of the statements marked (A) and (B) below provoke undefined behavior, why or why not, and (especially if you think one of them is well-defined but the other isn't), do you…
zwol
  • 135,547
  • 38
  • 252
  • 361
20
votes
4 answers

GCC: accuracy of strict aliasing warnings

I'm trying to check some of my code for strict aliasing violations, but it looks like I've missed something while trying to understand the strict aliasing rule. Imagine the following code: #include int main( void ) { unsigned long…
Macmade
  • 52,708
  • 13
  • 106
  • 123
19
votes
5 answers

Unions, aliasing and type-punning in practice: what works and what does not?

I have a problem understanding what can and cannot be done using unions with GCC. I read the questions (in particular here and here) about it but they focus the C++ standard, I feel there's a mismatch between the C++ standard and the practice (the…
L.C.
  • 1,098
  • 10
  • 21
19
votes
4 answers

C undefined behavior. Strict aliasing rule, or incorrect alignment?

I can't explain the execution behavior of this program: #include #include #include typedef char u8; typedef unsigned short u16; size_t f(u8 *keyc, size_t len) { u16 *key2 = (u16 *) (keyc + 1); size_t hash =…
Nikita Vorobyev
  • 313
  • 2
  • 9
1 2
3
37 38