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

What is the strict aliasing rule?

When asking about common undefined behavior in C, people sometimes refer to the strict aliasing rule. What are they talking about?
Benoit
  • 37,894
  • 24
  • 81
  • 116
133
votes
3 answers

Using this pointer causes strange deoptimization in hot loop

I recently came across a strange deoptimization (or rather missed optimization opportunity). Consider this function for efficient unpacking of arrays of 3-bit integers to 8-bit integers. It unpacks 16 ints in each loop iteration: void…
gexicide
  • 38,535
  • 21
  • 92
  • 152
115
votes
13 answers

In C++, should I bother to cache variables, or let the compiler do the optimization? (Aliasing)

Consider the following code (p is of type unsigned char* and bitmap->width is of some integer type, exactly which is unknown and depends on which version of some external library we're using): for (unsigned x = 0; x <…
Yaron Cohen-Tal
  • 2,005
  • 1
  • 15
  • 26
66
votes
2 answers

reinterpret_cast between char* and std::uint8_t* - safe?

Now we all sometimes have to work with binary data. In C++ we work with sequences of bytes, and since the beginning char was the our building block. Defined to have sizeof of 1, it is the byte. And all library I/O functions use char by default. All…
user3624760
64
votes
5 answers

Why can't the C compiler optimize changing the value of a const pointer assuming that two pointers to the same variable would be illegal/UB?

Recently I stumbled over a comparison between Rust and C and they use the following code: bool f(int* a, const int* b) { *a = 2; int ret = *b; *a = 3; return ret != 0; } In Rust (same code, but with Rust syntax), it produces the following…
izlin
  • 2,129
  • 24
  • 30
61
votes
6 answers

gcc, strict-aliasing, and horror stories

In gcc-strict-aliasing-and-casting-through-a-union I asked whether anyone had encountered problems with union punning through pointers. So far, the answer seems to be No. This question is broader: Do you have any horror stories about gcc and…
Joseph Quinsey
  • 9,553
  • 10
  • 54
  • 77
58
votes
7 answers

Violating of strict-aliasing in C, even without any casting?

How can *i and u.i print different numbers in this code, even though i is defined as int *i = &u.i;? I can only assuming that I'm triggering UB here, but I can't see how exactly. (ideone demo replicates if I select 'C' as the language. But as @2501…
Aaron McDaid
  • 26,501
  • 9
  • 66
  • 88
55
votes
3 answers

Is std::memcpy between different trivially copyable types undefined behavior?

I've been using std::memcpy to circumvent strict aliasing for a long time. For example, inspecting a float, like this: float f = ...; uint32_t i; static_assert(sizeof(f)==sizeof(i)); std::memcpy(&i, &f, sizeof(i)); // use i to extract f's sign,…
geza
  • 28,403
  • 6
  • 61
  • 135
54
votes
5 answers

"dereferencing type-punned pointer will break strict-aliasing rules" warning

I use a code where I cast an enum* to int*. Something like this: enum foo { ... } ... foo foobar; int *pi = reinterpret_cast(&foobar); When compiling the code (g++ 4.1.2), I get the following warning message: dereferencing type-punned pointer…
petersohn
  • 11,292
  • 13
  • 61
  • 98
52
votes
9 answers

Fix for dereferencing type-punned pointer will break strict-aliasing

I'm trying to fix two warnings when compiling a specific program using GCC. The warnings are: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] and the two culprits are: unsigned int received_size =…
BlankFrank
  • 523
  • 1
  • 4
  • 4
50
votes
3 answers

Why does optimisation kill this function?

We recently had a lecture in university about programming specials in several languages. The lecturer wrote down the following function: inline u64 Swap_64(u64 x) { u64 tmp; (*(u32*)&tmp) = Swap_32(*(((u32*)&x)+1)); …
guitarflow
  • 2,930
  • 25
  • 38
45
votes
7 answers

Dereferencing type-punned pointer will break strict-aliasing rules

I used the following piece of code to read data from files as part of a larger program. double data_read(FILE *stream,int code) { char data[8]; switch(code) { case 0x08: return (unsigned char)fgetc(stream); …
Framester
  • 33,341
  • 51
  • 130
  • 192
43
votes
4 answers

In C++, is it valid to treat scalar members of a struct as if they comprised an array?

While looking at the code for Dear Imgui, I found the following code (edited for relevance): struct ImVec2 { float x, y; float& operator[] (size_t idx) { return (&x)[idx]; } }; It's pretty clear that this works in practice, but from the…
38
votes
7 answers

gcc, strict-aliasing, and casting through a union

Do you have any horror stories to tell? The GCC Manual recently added a warning regarding -fstrict-aliasing and casting a pointer through a union: [...] Taking the address, casting the resulting pointer and dereferencing the result has undefined…
Joseph Quinsey
  • 9,553
  • 10
  • 54
  • 77
37
votes
2 answers

Correct, portable way to interpret buffer as a struct

The context of my problem is in network programming. Say I want to send messages over the network between two programs. For simplicity, let's say messages look like this, and byte-order is not a concern. I want to find a correct, portable, and…
croyd
  • 1,075
  • 1
  • 11
  • 15
1
2 3
37 38