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
8
votes
1 answer

_Bool type and strict aliasing

I was trying to write some macros for type safe use of _Bool and then stress test my code. For evil testing purposes, I came up with this dirty hack: _Bool b=0; *(unsigned char*)&b = 42; Given that _Bool is 1 byte on the implementation…
Lundin
  • 195,001
  • 40
  • 254
  • 396
8
votes
3 answers

Different behavior of shift operator with -O2 and without

Without -O2 this code prints 84 84, with O2 flag the output is 84 42. The code was compiled using gcc 4.4.3. on 64-bit Linux platform. Why the output for the following code is different? Note that when compiled with -Os the output is 0 42 #include…
Leonid
  • 22,360
  • 25
  • 67
  • 91
8
votes
1 answer

Is it okay for int** and const int** to alias?

It is my understanding that something like this is okay: const int ci = 42; const int *cip = &ci; int *ip = (int *)cip; int j = *ip; What about this? const int ci = 42; const int *cip = &ci; const int **cipp = &cip; int **ipp = (int **)cipp; int j…
Tavian Barnes
  • 12,477
  • 4
  • 45
  • 118
8
votes
4 answers

Strict aliasing rule and strlen implementation of glibc

I have been reading about the strict aliasing rule for a while, and I'm starting to get really confused. First of all, I have read these questions and some…
Yağmur Oymak
  • 467
  • 4
  • 13
8
votes
5 answers

gcc optimization skips initializing allocated memory

Using gcc 4.9.2 20150304 64 bit I bumped into this apparently strange behavior: double doit() { double *ptr = (double *)malloc(sizeof(double)); ptr[0] = 3.14; return (double)((uintptr_t) ptr); } In the code I'm allocating a double on…
6502
  • 112,025
  • 15
  • 165
  • 265
8
votes
2 answers

Strict pointer aliasing: is access through a 'volatile' pointer/reference a solution?

On the heels of a specific problem, a self-answer and comments to it, I'd like to understand if it is a proper solution, workaround/hack or just plain wrong. Specifically, I rewrote code: T x = ...; if (*reinterpret_cast (&x) == 0) …
user319799
8
votes
5 answers

Strict pointer aliasing: any solution for a specific problem?

I have a problem caused by breaking strict pointer aliasing rule. I have a type T that comes from a template and some integral type Int of the same size (as with sizeof). My code essentially does the following: T x = some_other_t; if…
user319799
8
votes
3 answers

How to create an uint8_t array that does not undermine strict aliasing?

I recently asked this question: Using this pointer causes strange deoptimization in hot loop The problem was that I was writing to an array of type uint8_t and the compiler treated it as if it could alias with the this pointer of the method (of type…
gexicide
  • 38,535
  • 21
  • 92
  • 152
8
votes
2 answers

C++ strict aliasing when not using pointer returned by placement new

Can this potentially cause undefined behaviour? uint8_t storage[4]; // We assume storage is properly aligned here. int32_t* intPtr = new((void*)storage) int32_t(4); // I know this is ok: int32_t value1 = *intPtr; *intPtr = 5; // But can one of…
rsp1984
  • 1,877
  • 21
  • 23
8
votes
4 answers

C/C++ strict aliasing, object lifetime and modern compilers

I am facing confusion about the C++ strict-aliasing rule and its possible implications. Consider the following code: int main() { int32_t a = 5; float* f = (float*)(&a); *f = 1.0f; int32_t b = a; // Probably not well-defined? float g =…
rsp1984
  • 1,877
  • 21
  • 23
8
votes
3 answers

Shared memory buffers in C++ without violating strict aliasing rules

I am struggling with implementing a shared memory buffer without breaking C99's strict aliasing rules. Suppose I have some code that processes some data and needs to have some 'scratch' memory to operate. I could write it as something like: void…
rsp1984
  • 1,877
  • 21
  • 23
8
votes
2 answers

Two arrays in a union in C++

is it possible to share two arrays in a union like this: struct { union { float m_V[Height * Length]; float m_M[Height] [Length]; } m_U; }; Do these two arrays share the same memory size or is…
Tobias
  • 427
  • 4
  • 19
7
votes
6 answers

How to safely perform type-punning in embedded system

Our team is currently using some ported code from an old architecture to a new product based on the ARM Cortex M3 platform using a customized version of GCC 4.5.1. We are reading data from a communications link, and attempting to cast the raw byte…
shenles
  • 562
  • 5
  • 19
7
votes
2 answers

Do I understand C/C++ strict-aliasing correctly?

I've read this article about C/C++ strict aliasing. I think the same applies to C++. As I understand, strict aliasing is used to rearrange the code for performance optimization. That's why two pointers of different (and unrelated in C++ case) types…
Andriy Tylychko
  • 15,967
  • 6
  • 64
  • 112
7
votes
5 answers

Why would the C standard (whatever is the latest) forbid this program due to strict aliasing?

It is clear to me that the C standard forbids (does not define the behavior of) this program, but it is not clear why it has to be this way. Why are the aliasing rules such that one cannot write this…