确实通过铸造访问原始记忆会违反严格的混叠
Does accessing raw memory through a cast to an int violate strict aliasing?
假设我想动态分配int
的空间,并将最大代表性值写入该内存。该代码想到:
auto rawMem = std::malloc(sizeof(int)); // rawMem's type is void*
*(reinterpret_cast<int*>(rawMem)) = INT_MAX; // INT_MAX from <limits.h>
该代码是否违反了C 关于严格混叠的规则?G 和Clang 都不向-Wall -pedantic
投诉。
如果代码不违反严格的混叠,为什么不呢?std::malloc
返回void*
,因此,尽管我不知道std::malloc
返回的内存的静态和动态类型,但没有理由认为这是int
。而且我们不会以char
或unsigned char
的方式访问内存。
我想认为代码是犹太洁食,但是如果是,我想知道为什么。
只要我在附近,我也想知道内存分配函数返回的内存的静态和动态类型(std::malloc
和std::operator new
)。
严格的混叠规则允许编译器假设可通过不同类型的两个或多个指针访问内存中的相同位置。
考虑以下代码:
int* pi = ...;
double* pd = ...;
const int i1 = *pi; // (1)
*pd = 123.456; // (2)
const int i2 = *pi; // (3)
用严格的混叠规则对此代码进行分析表明,i2 == i1
由于pi
指向的位置不应在(1)和(3)之间修改。因此,编译器可以消除一个变量i1
或i2
(前提是程序没有取决于其中任何一个的地址)。通常,严格的混叠规则在优化代码时为编译器提供了更多的自由。
在您的示例中,您可以通过malloc()
获得存储位置。编译器不假定该内存位置的任何类型(即该内存位置的静态和动态类型是...嗯...未型的原始内存,但是由于char[]
类型的特殊状态在严格的别名中规则我们还可以合法地将该内存位置视为char
s的数组。严格的别名规则尚未适用于新的内存位置,原因很简单,因为没有可以参与分析的打字指针。是您通过使用所需类型的对象将其指定为该位置的类型。如果是原始类型或POD类型,则reinterpret_cast
然后进行分配(就像您的示例中一样)是初始化该内存位置的有效方法,但是对于具有非平凡构造函数的类型,您需要与位置new
。从那时起,内存位置就停止了原始内存,并受到严格的混叠规则的约束。
- 将浮动的heightmap数组导出为16位原始值
- 给定一个向量,如何找到该向量的所有子集和的原始索引
- 松弛原子与无同步情况下的记忆连贯性
- 有没有办法从非C/C++文件中读取C++原始字符串文字的内容
- 是否可以将llvm::FunctionType转换为C/C++原始函数指针
- 递归函数有效,但无法记忆
- 如何将原始字节附加到 std::vector?
- 如何将记忆应用于此递归函数?
- 从堆栈分配的原始指针构造智能指针
- 如何重写全局方法名称以在调用原始方法之前将我的代码推到前面
- 将unique_ptr分配给原始指针
- 是否可以从 OpenGL 缓冲区获取原始大小的像素?
- 使用 OpenSSL 从内存中读取原始 SSL/TLS 证书
- 如何将唯一指针的 std::vector 转换为原始指针的 std::span?
- 从原始字节解码协议缓冲区(以 C++为单位)
- C ++如何在原始抽象类中创建一个函数,该函数接受派生类的输入
- 共享记忆:让我们谈谈它的特殊性
- C++:尝试使用等效的 STL 算法消除原始循环
- 为什么nlohmann不释放记忆
- 确实通过铸造访问原始记忆会违反严格的混叠