gpt4 book ai didi

c++ - 读/写部分分配的对齐内存

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:00:13 24 4
gpt4 key购买 nike

很多关于访问未分配内存的问题,这显然是未定义的行为。但是下面的极端情况呢。

考虑以下结构,它对齐到 16 个字节,但只占用其中的 8 个字节:

struct alignas(16) A
{
float data[2]; // the remaining 8 bytes are unallocated
};

现在我们通过 SSE 对齐加载/存储内在函数访问 16 个字节的数据:

__m128 test_load(const A &a)
{
return _mm_load_ps(a.data);
}

void test_store(A &a, __m128 v)
{
_mm_store_ps(a.data, v);
}

这也是未定义的行为吗?我应该改用填充吗?

无论如何,由于英特尔内在函数不是标准 C++,访问部分分配但对齐的内存块(不大于对齐的大小)是标准 C++ 中的未定义行为吗?

我同时处理了固有情况和标准 C++ 情况。我对他们两个都很感兴趣。

最佳答案

另见 Is it safe to read past the end of a buffer within the same page on x86 and x64?这个问题的阅读部分基本上是重复的。

根据 ISO C++ 标准,它是 UB,但我认为像这样的只读访问在提供英特尔内在函数(可以自由定义任何额外的他们想要的行为)。它在 asm 中绝对是安全的,但风险在于,优化将 UB 转换为错误编译代码的 C++ 编译器可能会导致问题,如果它们能够证明那里没有任何内容可读的话。在链接的问题上有一些讨论。


在对象之外写入总是不好的。不要这样做,即使您放回之前阅读的相同垃圾也不行:非原子加载/存储对可能是一个问题,具体取决于您的结构后面有哪些数据。

唯一可以的情况是在一个数组中,您知道接下来会发生什么,并且有未使用的填充。例如使用由 4B 重叠的 16B 存储写出一个 3-float 结构数组。 (没有用于过度对齐的 alignas,因此数组将它们打包在一起而没有填充)。


3 个 float 的结构比 2 个 float 更好。

对于这个特定示例(2 个 float ),您可以只使用 MOVSD 执行 64 位零扩展加载,并使用 MOVSD 或 MOVLPS 执行 __m128< 的低半部分的 64 位存储.

关于c++ - 读/写部分分配的对齐内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41152964/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com