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

Is ((size_t *)(vec))[-1] a violation of strict-aliasing?

A popular macro-based generic implementation of a vector in C (https://github.com/eteran/c-vector/blob/master/vector.h) uses the following memory layout. +------+----------+---------+ | size | capacity | data... | +------+----------+---------+ …
Shoaib Ahmed
  • 424
  • 2
  • 9
12
votes
0 answers

Is this a violation of strict aliasing rules?

According to the standard — 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),…
andrean
  • 6,717
  • 2
  • 36
  • 43
12
votes
1 answer

Could we access member of a non-existing class type object?

In the c++ standard, in [basic.lval]/11.6 says: 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:[...] an aggregate or union type that includes one…
Oliv
  • 17,610
  • 1
  • 29
  • 72
12
votes
2 answers

std::launder and strict aliasing rule

Consider this code: void f(char * ptr) { auto int_ptr = reinterpret_cast(ptr); // <---- line of interest // use int_ptr ... } void example_1() { int i = 10; f(reinterpret_cast(&i)); } void example_2() { …
phön
  • 1,215
  • 8
  • 20
12
votes
2 answers

Efficient conversion data one integer type to another with the same representation

The majority of microcomputer C compilers have two signed integer types with the same size and representation, along with two such unsigned types. If int is 16 bits, its representation will generally match short; if long is 64 bits, it will…
supercat
  • 77,689
  • 9
  • 166
  • 211
12
votes
3 answers

Is reinterpret_cast the only valid use of reinterpret_cast?

I recently learned that the C++ standard contains "strict aliasing rules", which forbid referencing the same memory location via variables of different types. However, the standard does allows for char types to legally alias any other type. Does…
digitale
  • 645
  • 4
  • 13
12
votes
1 answer

Does Visual C++ support "strict aliasing"?

I recently was surprised to learn that the C and C++ language standards have a "strict aliasing" rule. In essence, the rule prohibits variables of differing types from referencing the same memory location. As an example: char buffer[4] = { 0x55,…
digitale
  • 645
  • 4
  • 13
12
votes
1 answer

C aliasing rules and memcpy

While answering another question, I thought of the following example: void *p; unsigned x = 17; assert(sizeof(void*) >= sizeof(unsigned)); *(unsigned*)&p = 17; // (1) memcpy(&p, &x, sizeof(x)); // (2) Line 1 breaks aliasing rules. Line 2,…
zvrba
  • 24,186
  • 3
  • 55
  • 65
12
votes
4 answers

Simplest rule of thumb to avoid breaking strict-aliasing rules?

While read another question about aliasing ( What is the strict aliasing rule? ) and its top answer, I realised I still wasn't entirely satisfied even though I think I understood it all there. (This question is now tagged as C and C++. If your…
Aaron McDaid
  • 26,501
  • 9
  • 66
  • 88
12
votes
2 answers

In C++, What does "access" mean in the strict aliasing rule?

3.10/10 says: 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: However, the term "access" is not defined anywhere. In this context does it mean read,…
M.M
  • 138,810
  • 21
  • 208
  • 365
12
votes
1 answer

Strict aliasing in Rust?

My understanding is that the following code has undefined behaviour in C++ due to something called "strict aliasing rule". #include enum Foo : int16_t {}; void test(Foo& foo) { reinterpret_cast(foo) = 42; } In particular,…
kmky
  • 783
  • 6
  • 17
12
votes
3 answers

Do pointers to pointers to structs have implied interchangeability?

According to both C99 §6.2.5p27 and C11 §6.2.5p28: All pointers to structure types shall have the same representation and alignment requirements to each other. With a footnote (#39 and #48 respectively): The same representation and alignment…
Dror K.
  • 1,989
  • 17
  • 26
12
votes
4 answers

Am I breaking strict aliasing rules?

I would like to know if I'm breaking strict aliasing rules with this snippet. (I think so since it's dereferencing a punned-pointer, however it's done in a single expression and /Wall doesn't cry.) inline double plop() const // member function { …
PixelRick
  • 149
  • 1
  • 8
11
votes
4 answers

C memory allocator and strict aliasing

even after reading quite a bit about the strict-aliasing rules I am still confused. As far as I have understood this, it is impossible to implement a sane memory allocator that follows these rules, because malloc can never reuse freed memory, as the…
11
votes
2 answers

Buffer filled with different types of data, and strict aliasing

According to the standard, it is always undefined behavior in C++ to make, for example, a float* point to the same memory location as a int*, and then read/write from them. In the application I have, there can be a buffer filled with 32-bit integer…
tmlen
  • 8,533
  • 5
  • 31
  • 84