使用malloc的结构数据对齐

时间:2018-09-03 19:25:40

标签: c malloc memory-alignment

考虑一下我的结构如下。

struct st
{
  char c;
  double d;
  int i;
};

根据struct st的内存对齐大小将为(1 + 7(已填充)+ 8 + 4 + 4(已填充))= 24字节

当我按如下所述进行malloc

struct st *p = malloc(sizeof(*p));

它将与

相同
struct st *p = malloc(13);

由于我们只是传递结构的大小(13bytes),因此malloc如何分配24个字节以满足内存对齐?

2 个答案:

答案 0 :(得分:4)

这个问题错误地认为

struct st *p = malloc(sizeof(*p));

相同
struct st *p = malloc(13);

不是。要测试,

printf ("Size of st is %d\n", sizeof (*p));

打印24,而不是13。

分配和管理结构的正确方法是使用sizeof(X),而不是假设元素是如何打包或对齐的。

答案 1 :(得分:0)

  

malloc如何分配24个字节以满足内存对齐,因为我们只是传递结构的大小(13个字节)?

不是。如果malloc(13)恰好返回了至少24个字节,则这是malloc实现的怪癖。允许malloc分配超出必要的空间,并且通常出于字节对齐和各种其他实现原因而必须。

我们可以通过一个简单的程序看到它。

struct st *a = malloc(13);
struct st *b = malloc(13);
struct st *c = malloc(13);
struct st *d = malloc(13);

printf("%p\n%p\n%p\n%p\n", a, b, c, d);

0x602000003210
0x602000003230
0x602000003250
0x602000003270

从地址中可以看到,malloc(13)返回的指针之间有32个字节。足够容纳您的24个字节,程序可以正常运行。甚至malloc(1)也会返回相同的结果。

但是,如果我们使您的结构大一点……

struct st {
  char c;
  double b;
  double a;
  double d;
  int i;
};

这是40个字节,对齐。现在它不能容纳32个字节,由于结构的内存相互重叠,我们看到了损坏。

#include <stdlib.h>
#include <stdio.h>

struct st {
  char c;
  double b;
  double a;
  double d;
  int i;
};

void print_struct(struct st* st) {
    printf("%c %lf %d\n", st->c, st->d, st->i);
}

int main() {
    const size_t struct_size = sizeof(char) + (sizeof(double) * 3) + sizeof(int);

    printf("sizeof(struct st): %zu\n", sizeof(struct st));
    printf("sizeof fields added together: %zu\n", struct_size);

    struct st *a = malloc(13);
    struct st *b = malloc(13);
    struct st *c = malloc(13);
    struct st *d = malloc(13);

    printf("%p\n%p\n%p\n%p\n", a, b, c, d);

    a->c = 'a';
    a->d = 1.0;
    a->i = 1;

    b->c = 'b';
    b->d = 2.0;
    b->i = 2;

    c->c = 'c';
    c->d = 3.0;
    c->i = 3;

    d->c = 'd';
    d->d = 4.0;
    d->i = 4;

    print_struct(a);
    print_struct(b);
    print_struct(c);
    print_struct(d);
}

sizeof(struct st): 40
sizeof fields added together: 29
0x602000003210
0x602000003230
0x602000003250
0x602000003270
a 1.000000 98
b 2.000000 99
c 3.000000 100
d 4.000000 4

98是ascii b。 99是ascii c。 100为ascii d。这表明a->ib->c重叠,b->ic->c重叠,依此类推。