标签: memory-alignment

使用 C++11 的 MinGW 和打包结构对齐

对于下面的结构,结构的实际(没有填充)大小为 54。在具有 MinGW (GCC) 4.8.1 x86_64 的 64 位 (Windows 7) 计算机上,我得到的大小sizeof(BMPHeader)为 56,这是可以理解的。根据BMP文件格式的要求,该结构不应有填充。我有三个选择(优先顺序):

  1. C++11的alignas(1)
  2. struct __attribute__ ((packed)) BMPHeader
  3. #pragma pack(1)

然而,最后一个选项(优先级最低)似乎单独工作,给了我 54。这是编译器中的错误还是我在这里完全误解了一些东西?南沙商会

#include <iostream>

struct alignas(1) BMPHeader
{
    // BMP header
    uint16_t magic;
    uint32_t fileSize;
    uint32_t reserved;
    uint32_t dataOffset;

    // DIB header
    uint32_t dibHeaderLength;
    uint32_t width;
    uint32_t height;
    uint16_t numColourPlanes;
    uint16_t bitsPerPixels;
    uint32_t biBitFields;
    uint32_t dataSize;
    uint32_t physicalWidth;
    uint32_t physicalHeight;
    uint32_t numPaletteColours;
    uint32_t numImportantColours;
};

int main()
{
    std::cout << sizeof(BMPHeader) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

struct mingw g++ memory-alignment c++11

3
推荐指数
1
解决办法
1987
查看次数

为什么不能一步读取未对齐的单词?

鉴于 CPU 的字长允许它寻址内存中的每个字节。
鉴于通过PAE CPU 甚至可以使用比其字长更多的位进行寻址。

CPU无法一步读取未对齐的字是什么原因?

例如,在 32 位机器中,您可以读取从位置 0 开始的 4 字节块,但不能读取从位置 1 开始的块(可以,但需要几个步骤)。
为什么CPU不能这样做?

hardware cpu-architecture memory-alignment memory-address address-bus

3
推荐指数
1
解决办法
310
查看次数

通过强制转换在 uint8_t[8] 和 uint64_t 之间安全转换?

我目前这样做的方式(我宁愿摆脱memcpy电话):

uint64_t integer;
uint8_t string[8];
...
memcpy(&integer, &string, 8); //or swap the parameters
Run Code Online (Sandbox Code Playgroud)

假设integer数组长度始终是 8 的倍数(64 位总分配),考虑到编译器填充/对齐问题,是否可以进行直接转换?

c optimization casting memory-alignment memcpy

3
推荐指数
1
解决办法
4108
查看次数

内存对齐 QVector().data()

我正在使用 Qt5 编写一个程序,我需要分配一个QVector <float>使其data()指针 32 字节对齐的指针。

无论如何,我可以在不修改 Qt 库本身的情况下做到这一点吗?

我的代码看起来像这样:

QVector <float> vec;
vec.resize(n);
float *wricker_ptr = wricker.data(); // this should be 32-byte aligned
for (int i=0; i<n; i++)
{
    wricker_ptr[i] = /* some computed value */;
}
Run Code Online (Sandbox Code Playgroud)

我正在使用英特尔的 C++ 编译器。

qt vectorization memory-alignment qt5 auto-vectorization

3
推荐指数
1
解决办法
455
查看次数

向 MPI 结构添加填充

我有一个 C 结构数组,我想填充它来读取文件(并行,使用 set_view 等)

typedef struct
{
    char   type;
    double value;
    double velocity;
} Cell;
Run Code Online (Sandbox Code Playgroud)

我的问题是,一些文件(TYPE1)将只具有typevalue(与速度的情况下,必须留给O,以及其他一些文件(2型)都在我typevaluevelocity

因此,在读取n文件中的块时,我要么读取 nx 9 位(case1)要么读取 nx 17 位((case2),我必须将它们以良好的对齐方式放入缓冲区。

我从一个mpi_cell_aligned类型开始

MPI_Datatype mpi_cell_aligned;
int          count[] = { 1,                    1,                     1                        };
MPI_Aint     displ[] = { offsetof(Cell, type), offsetof(Cell, value), offsetof(Cell, velocity) };
MPI_Datatype types[] = { MPI_CHAR,             MPI_DOUBLE,            MPI_DOUBLE               };
switch(type)
{
    case 1: MPI_Type_create_struct(2, count, displ, types, &mpi_cell_aligned); break;
    case 2: MPI_Type_create_struct(3, …
Run Code Online (Sandbox Code Playgroud)

io types mpi memory-alignment

3
推荐指数
1
解决办法
323
查看次数

GCC 中的 `movaps` 与 `movups`:它是如何决定的?

我最近研究了一个用GCC 8编译的软件中的segfault。代码如下(这只是一个草图)

struct Point
{
  int64_t x, y;
};

struct Edge
{
  // some other fields
  // ...
  Point p; // <- at offset `0xC0`

  Edge(const Point &p) p(p) {}
};

Edge *create_edge(const Point &p)
{
  void *raw_memory = my_custom_allocator(sizeof(Edge));
  return new (raw_memory) Edge(p);
}
Run Code Online (Sandbox Code Playgroud)

这里的关键点是my_custom_allocator()返回指向未对齐内存的指针。代码崩溃是因为为了将原始点复制pEdge::p新对象的字段中,编译器在 [内联] 构造函数代码中使用了movdqu/movaps

movdqu 0x0(%rbp), %xmm1  ; read the original object at `rbp`
...
movaps %xmm1, 0xc0(%rbx) ; store it into the new `Edge` object …
Run Code Online (Sandbox Code Playgroud)

c++ optimization x86 gcc memory-alignment

3
推荐指数
1
解决办法
1802
查看次数

当 sizeof 的大小与实际对象大小不匹配时,一切如何工作(包括运算符“-&gt;”)?

在下面的代码中,我定义了一个9 字节的结构,它与 16 字节的大小对齐。然后我从堆中动态分配 9 个字节并将其分配给标头指针。

struct header                 
{
     uint8_t chunk_id;               
     long int format;                 
};

int main()
{   
    std::cout << "sizeof(header) " << sizeof(header) << '\n';

    auto head = (header*)malloc(9);
    head->chunk_id =3;
    head->format=5;    
    std::cout << (int)head->chunk_id << " " << head->format << '\n' << sizeof(*head);

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

输出:

sizeof(header) 16
3 5
16
Run Code Online (Sandbox Code Playgroud)

事实证明,sizeof仍然通知这个对象是 16 个字节(尽管它是 9 个)。我想它只是看结构的定义。但是,当sizeof的大小与实际对象大小不匹配时,一切如何工作(包括运算符“->”)?

c++ struct memory-alignment

3
推荐指数
1
解决办法
55
查看次数

alignof 和 alignas C++ 关键字的实际用例

我刚刚了解alignofalignasC ++的关键字,但我不敢去想如果开发者希望使用这些关键字的任何实际的案例。

有人知道这些关键字的任何实际用例吗?

c++ memory-alignment memory-layout c++11

3
推荐指数
1
解决办法
317
查看次数

在 NASM 中调用函数之前,%rsp 是否应该与 16 字节边界对齐?

我从 NASM 的文档中看到了以下规则:

在进行调用之前,堆栈指针 %rsp 必须与 16 字节边界对齐。很好,但是进行调用的过程会将返回地址(8 个字节)压入堆栈,因此当函数获得控制权时,%rsp 未对齐。你必须自己创造额外的空间,通过推动某些东西或从 %rsp 中减去 8。

我有一段 NASM 汇编代码,如下所示:

在我调用“_start”中的函数“inc”之前,%rsp 应该位于 8 字节的边界,这违反了 NASM 文档中描述的规则。但实际上,一切都在进行中。那么,我如何理解这一点呢?

我是在 Ubuntu 20.04 LTS (x86_64) 下构建的。

global _start

section .data
init:
    db 0x2

section .rodata
codes: 
    db '0123456789abcdef'

section .text
inc:
    mov rax, [rsp+8]  ; read param from the stack;
    add rax, 0x1
    ret

print:
    lea rsi, [codes + rax]
    mov rax, 1
    mov rdi, 1
    mov rdx, 1
    syscall
    ret

_start:
    ; enable AC check;
    pushf
    or …
Run Code Online (Sandbox Code Playgroud)

linux assembly x86-64 calling-convention memory-alignment

3
推荐指数
1
解决办法
477
查看次数

C 结构成员是否继承编译器属性?

对于大多数 C 编译器,可以在结构上指定编译器属性,该属性定义该结构的成员在内存中的对齐方式。前任:

typedef struct{
    char a;
    char b;
} __attribute__((aligned(2))) TwoChars;

Run Code Online (Sandbox Code Playgroud)

如果char a以地址 0xA 结束(为简单起见),则char b不会在地址 0xB 处,而是在 0xC 处,因为它与 2 个字节对齐。

我的问题是:这个属性是由结构成员继承的吗?前任:

typedef struct{
    char a;
    char b;
} TwoChars;

typedef struct {
    TwoChars tc;
    char c;
} __attribute__((aligned(1))) ThreeChars;
Run Code Online (Sandbox Code Playgroud)

这在内存中最终会是什么样子?怎么样} __attribute__((aligned(2))) TwoChars

c gcc struct memory-alignment

3
推荐指数
1
解决办法
74
查看次数