读取 /编写部分分配的对齐内存



关于访问未分配记忆的问题有一个 lot ,这显然是未定义的行为。但是以下角色呢?

考虑以下结构,该结构与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);
}

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

无论如何,由于Intel Interins不是标准的C ,因此正在访问标准C ?

i同时解决内在案例和标准C 情况。我对他们两个都感兴趣。

另请参阅x86和x64上同一页面中的缓冲区末端读取缓冲区的末端是否安全?这个问题的阅读部分基本上是对此的重复。

根据ISO C 标准是UB,但我认为这样的仅阅读访问确实可以安全起作用(即您期望的ASM汇编)在提供Intel Intrinsics的实现(可以自由定义额外的任何内容)上他们想要的行为)。在ASM中,这绝对是安全的,但是风险是优化将UB转换为错误编译的代码的C 编译器,如果他们能证明没有什么可阅读的,可能会导致问题。关于链接的问题有一些讨论。


在对象外写作总是不好的。不要这样做,即使您放回了之前阅读的相同垃圾:非原子负载/商店对也可能是一个问题,具体取决于您的结构的数据。

这唯一可以在一个阵列中,您知道接下来会发生什么,并且有未使用的填充。例如使用16B商店与4B重叠的16B商店编写3-float结构的数组。(没有alignas进行过度对齐,因此一个数组将它们包装在一起而无需填充)。


3 float s的结构比2 floats要好得多。

对于此特定示例(2个浮子),您只需使用MovsD即可进行64位零延伸负载,然后MovsD或Movlps可以在__m128的低半处进行64位商店。

语言律师对此的回答是'问题是毫无意义的。_mm_load_ps未在标准中定义,并且它使用的是ASM指令,该指令也不在标准中定义。C 不处理此。

至于您的第二个问题 - 从C 访问未分配的内存显然是未定义的行为。在此内存中没有任何对象,因此您无法访问它。

最新更新