标签: memory-alignment

C和C++中的堆数组与宽松编译器(GCC)矢量化的对齐

我正在编写一个包装器容器模板类,std::vector它会自动创建一个multi-resolution pyramid元素std::vector.

现在的关键问题是我希望金字塔的创建是(GCC)自动矢量化的.

内部存储在std :: vector和我的解析金字塔中的所有数据数组都是使用标准的new或allocator模板参数在堆上创建的.有没有我可以帮助编译器强制对我的数据进行特定对齐,以便矢量化可以在具有最佳对齐的元素(数组)(块)上运行(通常为16).

因此我使用自定义分配器, AlignmentAllocator但GCC自动向量化消息输出仍然在第144行中声明包含表达式的未对齐内存std::mr_vector::construct_pyramidmulti_resolution.hpp

for (size_t s = 1; s < snum; s++) { // for each cached scale
...
}
Run Code Online (Sandbox Code Playgroud)

如下

tests/../multi_resolution.hpp:144: note: Detected interleaving *D.3088_68 and MEM[(const value_type &)D.3087_61]
tests/../multi_resolution.hpp:144: note: versioning for alias required: can't determine dependence between *D.3088_68 and *D.3082_53
tests/../multi_resolution.hpp:144: note: mark for run-time aliasing test between *D.3088_68 and *D.3082_53
tests/../multi_resolution.hpp:144: note: versioning for alias …
Run Code Online (Sandbox Code Playgroud)

c++ gcc vectorization memory-alignment dynamic-memory-allocation

8
推荐指数
1
解决办法
1270
查看次数

带有"空类"的C++多重继承内存布局

我知道多继承的内存布局没有定义,所以我不应该依赖它.但是,我可以在特殊情况下依赖它.也就是说,一个班级只有一个"真正的"超级班级.所有其他都是"空类",即既没有字段也没有虚拟方法的类(即它们只有非虚方法).在这种情况下,这些附加类不应该向类的内存布局添加任何内容.(更简洁地说,在C++ 11中,该类具有标准布局)

我可以推断出所有超类都没有偏移吗?例如:

#include <iostream>

class X{

    int a;
    int b;
};

class I{};

class J{};

class Y : public I, public X,  public J{};

int main(){

    Y* y = new Y();
    X* x = y;
    I* i = y;
    J* j = y;

    std::cout << sizeof(Y) << std::endl 
                  << y << std::endl 
                  << x << std::endl 
                  << i << std::endl 
                  << j << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

这里,YX是唯一真正的基类.程序的输出(在linux上用g ++ 4.6编译时)如下:

8

0x233f010

0x233f010

0x233f010

0x233f010 …

c++ multiple-inheritance memory-alignment

8
推荐指数
1
解决办法
2508
查看次数

为什么对齐long long union成员比包含union/struct更大?它是否正确?

这个问题开始,人们可以开始相信联盟的一致性不低于其个体成员的最大一致性.但我对long longgcc/g ++中的类型有问题.完整的示例可以在这里找到,但这里是我的问题的相关部分:

union ull {
  long long m;
};

struct sll {
  long long m;
};


int main() {
#define pr(v) cout << #v ": " << (v) << endl
   pr(sizeof(long long));
   pr(__alignof__(long long));
   pr(sizeof(ull));
   pr(__alignof__(ull));
   pr(sizeof(sll));
   pr(__alignof__(sll));
};
Run Code Online (Sandbox Code Playgroud)

这导致以下输出:

sizeof(long long): 8
__alignof__(long long): 8
sizeof(ull): 8
__alignof__(ull): 4
sizeof(sll): 8
__alignof__(sll): 4
Run Code Online (Sandbox Code Playgroud)

为什么union成员的对齐大于包含union的对齐?

[UPDATE]

根据基思的回答,对齐在这里是错误的.但我测试了以下内容,似乎alignof 告诉我们真实情况.看到:

union ull {
  long long m;
};
long long a;
char b; …
Run Code Online (Sandbox Code Playgroud)

c++ g++ memory-alignment unsigned-long-long-int unions

8
推荐指数
1
解决办法
1249
查看次数

未对齐访问会导致ARM Cortex-M4出错

我有一个对象,其地址不是4字节对齐的.当存在STR指令保存2个寄存器时,这会在cpu中导致HardFault错误.

这是生成的代码:

   00000000 <_ZN8BaseAreaC1EPcmm>:
   0:   b510            push    {r4, lr}
   2:   4604            mov     r4, r0
   4:   6042            str     r2, [r0, #4]
   6:   e9c4 3102       strd    r3, r1, [r4, #8]
   a:   2001            movs    r0, #1
   c:   7420            strb    r0, [r4, #16]
   e:   b921            cbnz    r1, 1a <_ZN8BaseAreaC1EPcmm+0x1a>
Run Code Online (Sandbox Code Playgroud)

这些是在"4:6042 ......"行的寄存器

R0   08738B82  R8          0  
R1   08738BAE  R9          0  
R2          0  R10  082723E0  
R3       2FCC  R11         0  
R4   08738B82  R12         0  
R5   20007630  R13  2000CB38  
Run Code Online (Sandbox Code Playgroud)

如图所示,STR指令的目标寄存器未在4字节上对齐.该指令STR r2, [r0, #4]执行正常.但它就是HardFaults的下一个STRD r3, r1, …

c c++ arm memory-alignment cortex-m

8
推荐指数
1
解决办法
9896
查看次数

数组的内存对齐方式

我在Cell处理器上调整DMA传输的内存时遇到问题.我需要地址的最后4位为0.

我有4个数组,unsigned int其中每个元素必须在内存中对齐,以便其(十六进制)地址以零结尾.

例如

int main()
{
    size_t i;

    static unsigned int a[2] __attribute__ ((aligned (16)));
    static unsigned int b[2] __attribute__ ((aligned (16)));
    static unsigned int c[2] __attribute__ ((aligned (16)));
    static unsigned int d[2] __attribute__ ((aligned (16)));

    for (i = 0; i < 2; ++i) {
        printf("a[%u] = %p\n", &a[i]);
        printf("b[%u] = %p\n", &b[i]);
        printf("c[%u] = %p\n", &c[i]);
        printf("d[%u] = %p\n", &d[i]);
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

a[0] = 0x10010b60
b[0] = 0x10010b50
c[0] = 0x10010b40 …
Run Code Online (Sandbox Code Playgroud)

c memory-alignment dma

8
推荐指数
2
解决办法
1万
查看次数

特征对齐问题

文档中列出的Eigen的内存对齐问题是否仍然适用于C++ 11?似乎C++ 11已经能够正确地对齐堆栈上和堆上的对象,alignas并且std::allocator支持对齐.

memory-alignment eigen c++11 eigen3

8
推荐指数
1
解决办法
862
查看次数

SSE:跨越页面边界的未对齐加载和存储

我在某处读到了在页面边界旁边执行未对齐的加载或存储之前(例如使用_mm_loadu_si128/ _mm_storeu_si128intrinsics),代码应首先检查整个向量(在这种情况下是16个字节)是否属于同一页面,如果不是,则切换到非向量指令.我知道如果下一页不属于进程,则需要这样做以防止coredump.

但是,如果两个页面都属于进程(例如,它们是一个缓冲区的一部分,并且我知道该缓冲区的大小),该怎么办?我写了一个小的测试程序,它执行了未对齐的加载和跨越页面边界的存储,并没有崩溃.在这种情况下,我是否必须始终检查页面边界,还是足以确保我不会溢出缓冲区?

环境:Linux,x86_64,gcc

c linux sse x86-64 memory-alignment

8
推荐指数
1
解决办法
688
查看次数

什么阻止__attribute __((packed))进入ISO C/C++?

这是我在编写某些类系统软件时使用C/C++的最重要原因之一,但它只不过是一个非常常见的编译器扩展.为什么委员会不考虑正式支持它?它是否与现有规范中的任何子句不兼容,例如public和private是否对对象的内存布局有影响?

c c++ attributes memory-alignment

8
推荐指数
1
解决办法
143
查看次数

x86程序集中堆栈对齐的响应性

我试图清楚地了解谁(调用者或被调用者)负责堆栈对齐.64位汇编的情况相当清楚,它是由调用者.

参考System V AMD64 ABI,第3.2.2节"堆栈帧":

输入参数区域的末尾应在16(32,如果在堆栈上传递__m256)字节边界上对齐.

换句话说,应该可以安全地假设,对于被调用函数的每个入口点:

16 | (%rsp + 8)

保持(额外八个是因为call隐含地在堆栈上推送返回地址).

它在32位世界中的表现(假设是cdecl)?我注意到,使用以下构造gcc将对齐放置在被调用函数:

and esp, -16
Run Code Online (Sandbox Code Playgroud)

这似乎表明,这是被召唤者的责任.

为了更清楚,请考虑以下代码:

global main
extern printf
extern scanf
section .rodata
    s_fmt   db "%d %d", 0
    s_res   db `%d with remainder %d\n`, 0
section .text
main:
    start   0, 0
    sub     esp, 8
    mov     DWORD [ebp-4], 0 ; dividend
    mov     DWORD [ebp-8], 0 ; divisor

    lea     eax, [ebp-8]
    push …
Run Code Online (Sandbox Code Playgroud)

linux x86 assembly gcc memory-alignment

8
推荐指数
1
解决办法
4196
查看次数

容器中过度对齐的结构和枚举之间的C ++差异

在C ++中,至少在GCC和Clang上,嵌入在容器(std :: vector)中的超对齐类型似乎被不同地对待,具体取决于该类型是超对齐结构还是超对齐枚举。对于struct版本,每个元素都对齐,而对于枚举,只有整个缓冲区具有指定的对齐方式。该行为是否由标准指定?如果是这样,哪一部分提到了?还是实现定义的,不应该依赖?

考虑以下:

#include<cstdint>
#include<iostream>
#include<vector>

struct alignas(16) byte_struct {std::uint8_t value;};
enum alignas(16) byte_enum : std::uint8_t {};

int main() {
    {//with struct
        std::vector<byte_struct> bytes;
        bytes.push_back(byte_struct{1});
        bytes.push_back(byte_struct{2});
        bytes.push_back(byte_struct{3});
        for(auto it = bytes.begin(); it!= bytes.end(); ++it) {
                std::cout<<&*it<<std::endl;
        }
    }
    {//with enum
        std::vector<byte_enum> bytes;
        bytes.push_back(byte_enum{1});
        bytes.push_back(byte_enum{2});
        bytes.push_back(byte_enum{3});
        for(auto it = bytes.begin(); it!= bytes.end(); ++it) {
                std::cout<<&*it<<std::endl;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

具有过度对齐的结构的版本将打印以下内容

0x10a9ec0 0x10a9ed0 0x10a9ee0

带有过度对齐的枚举的版本将打印以下内容

0x10a9e70 0x10a9e71 0x10a9e72

在向量存储区中,每个byte_struct都对齐到16个字节的边界,而byte_enum的对齐方式只适用于整个缓冲区,而不适用于每个单独的元素。

在GCC 9.1和Clang 8.0上,此行为相同,而MSVC 19.20遇到内部编译器错误。

编译器资源管理器的链接为:https : //godbolt.org/z/GUg2ft

c++ memory-alignment language-lawyer c++17

8
推荐指数
1
解决办法
165
查看次数