使用属性对齐时的内存对齐(1)

时间:2016-07-08 06:20:21

标签: c memory-alignment

我正在调试以下代码片段来分析结构成员的字节对齐。

#include <stdio.h>
#include <stdint.h>
#include <string.h>

struct v_hdr {
    uint16_t vlan_tci;
    uint16_t eth_proto;
}__attribute__((aligned(1)));

struct esp_hdr {
    uint32_t fpa_esp_spi;
    uint32_t fpa_esp_sequenceid;
}__attribute__((aligned(1)));

struct f_cookie {
    uint16_t vlan_ports;
    uint16_t untagged_vlan_ports;
    struct v_hdr vlan_hdr;
    uint16_t tcp_flags;
    uint32_t *eth_hdr;
    uint32_t *ipv4_hdr;
    struct esp_hdr esp;
}__attribute__((aligned(1)));

struct metadata {
    struct f_cookie flow_cookie;
} __attribute__((aligned(1)));

int main ()
{
    struct metadata meta;
    memset (&meta, 0, sizeof(struct metadata));

    /* 16 */ meta.flow_cookie.vlan_ports             = 0xffff;
    /* 16 */ meta.flow_cookie.untagged_vlan_ports    = 0xffff;
    /* 16 */ meta.flow_cookie.vlan_hdr.vlan_tci      = 0xffff;
    /* 16 */ meta.flow_cookie.vlan_hdr.eth_proto     = 0xffff;
    /* 16 */ meta.flow_cookie.tcp_flags              = 0xffff;
    /* 32 */ meta.flow_cookie.eth_hdr                = 0xffffffff;
    /* 32 */ meta.flow_cookie.ipv4_hdr               = 0xffffffff;
    /* 32 */ meta.flow_cookie.esp.fpa_esp_spi        = 0xffffffff;
    /* 32 */ meta.flow_cookie.esp.fpa_esp_sequenceid = 0xffffffff;

    return 0;
}

这是返回语句之前的gdb x转储 -

(gdb) p sizeof meta
$2 = 40

(gdb) x/40bt &meta
0x7fffffffe2d0: 11111111        11111111        11111111        11111111        11111111        11111111        11111111        11111111
0x7fffffffe2d8: 11111111        11111111        00000000        00000000        00000000        00000000        00000000        00000000
0x7fffffffe2e0: 11111111        11111111        11111111        11111111        00000000        00000000        00000000        00000000
0x7fffffffe2e8: 11111111        11111111        11111111        11111111        00000000        00000000        00000000        00000000
0x7fffffffe2f0: 11111111        11111111        11111111        11111111        11111111        11111111        11111111        11111111

我的问题是为什么在meta.flow_cookie.eth_hdr之后tcp_flags没有放在4字节边界?即在(0x7fffffffe2d8 + 4)。而meta.flow_cookie.ipv4_hdr不在0x7fffffffe2e0

尽管应用了aligned(1)属性,为什么这两个成员都被置于8字节边界? PS。我不想使用属性packed。我只希望成员尽可能与4字节地址对齐。它可以实现吗?

1 个答案:

答案 0 :(得分:2)

引用代码的摘录:

/* 16 */ meta.flow_cookie.tcp_flags              = 0xffff;
/* 32 */ meta.flow_cookie.eth_hdr                = 0xffffffff;
/* 32 */ meta.flow_cookie.ipv4_hdr               = 0xffffffff;

您认为meta.flow_cookie.eth_hdrmeta.flow_cookie.ipv4_hdr 指针是32位长,而您的系统(基于gdb转储)并不是&# 39; t似乎是一个32位架构。

请注意,sizeof(uint32_t *)sizeof(uint32_t)不同。如果由于某种原因,这些值是相同的(在32位架构的情况下),这是纯粹的巧合。

指针的大小总是足以容纳属于底层架构的完整地址空间的任何地址。例如,64位架构上的sizeof(uint32_t *)至少需要8个字节(64位长)。

由于您的架构似乎具有64位地址空间,因此您对对齐所做的假设存在缺陷。