Reputation: 13512
Suppose I want to dynamically allocate space for an int
and write the maximum representable value into that memory. This code comes to mind:
auto rawMem = std::malloc(sizeof(int)); // rawMem's type is void*
*(reinterpret_cast<int*>(rawMem)) = INT_MAX; // INT_MAX from <limits.h>
Does this code violate C++'s rules about strict aliasing? Neither g++ nor clang++ complain with -Wall -pedantic
.
If the code doesn't violate strict aliasing, why not? std::malloc
returns void*
, so while I don't know what the static and dynamic types of the memory returned by std::malloc
are, there's no reason to think either is int
. And we're not accessing the memory as a char
or unsigned char
.
I'd like to think the code is kosher, but if it is, I'd like to know why.
As long as I'm in the neighborhood, I'd also like to know the static and dynamic types of the memory returned by the memory allocation functions (std::malloc
and std::operator new
).
Upvotes: 5
Views: 349
Reputation: 32484
Strict aliasing rule allows the compiler to assume that the same location in memory cannot be accessed through two or more pointers of different types.
Consider the following code:
int* pi = ...;
double* pd = ...;
const int i1 = *pi; // (1)
*pd = 123.456; // (2)
const int i2 = *pi; // (3)
Analysis of this code with the strict aliasing rule in mind suggests that i2 == i1
, since the location pointed by pi
should not be modified between (1) and (3). The compiler can therefore eliminate one of the variables i1
or i2
(provided that the program doesn't take the address of either of them). In general, strict aliasing rule gives more freedom to the compiler while optimizing the code.
In your example you obtain a memory location through malloc()
. The compiler doesn't assume any type for that memory location (i.e. both the static and dynamic type of that memory location is ... ummm... untyped raw memory, however due to the special status of the char[]
type in the strict aliasing rule we can also legally treat that memory location as an array of char
s). The strict aliasing rule doesn't yet apply to the new memory location for the simple reason that there is no typed pointer that can be involved in the analysis. It is you that designate a type to that location by initializing it with an object of the desired type. In case of a primitive type or a POD type, a reinterpret_cast
followed by assignment (just like in your example) is a valid way to initialize that memory location, but for types with a non-trivial constructor you would need to construct an object with placement new
. From that very moment, the memory location stops being raw memory, and is subject to the strict aliasing rule.
Upvotes: 4