【问题标题】:gcc sizeof(struct) giving unexpected valuegcc sizeof(struct) 给出了意想不到的值
【发布时间】:2011-11-29 13:31:26
【问题描述】:

我正在编写一个程序来解压 PE 文件。我有一个结构 Pe_SymbolHeader。它看起来像这样:

typedef struct _Pe_SymbolHeader {
    char Name[8];                // 8
    uint32_t Value;              // 12
    uint16_t SectionNumber;      // 14
    uint16_t Type;               // 16
    uint8_t  StorageClass;       // 17
    uint8_t  NumberOfAuxSymbols; // 18
} Pe_SymbolHeader;

gcc 告诉我这个结构的大小是 20 字节。

printf("sizeof Pe_SymbolHeader %d\n", sizeof(Pe_SymbolHeader));

我决定在堆栈上放置一个 Pe_SymbolHeader 并查看所有内容在内存中的位置

Pe_SymbolHeader test

printf("%p\n", &(test.Name));
printf("%p\n", &(test.Value));
printf("%p\n", &(test.SectionNumber));
printf("%p\n", &(test.Type));
printf("%p\n", &(test.StorageClass));
printf("%p\n", &(test.NumberOfAuxSymbols));

这给了我以下,这似乎没问题:

0x7fffffffe150
0x7fffffffe158
0x7fffffffe15c
0x7fffffffe15e
0x7fffffffe160
0x7fffffffe161

如果 gcc 使用 18 个字节来存储我的结构,为什么 sizeof 告诉我结构将占用 20 个字节?

编辑:好的,看来 gcc 正在尝试帮助我的事情正在杀死我,并且有几个答案是正确的。我只能投一个,但感谢那些回答的人。

【问题讨论】:

  • 真正的关键词是alignmentpadding (

标签: gcc alignment


【解决方案1】:

因为对齐的填充


结构的末尾有填充。

原因与数组中发生的事情有关,或者可能与结构之后的某些其他上下文有关。那东西可能是这个结构的另一个实例。该结构包含一个 32 位对象,因此它的对齐要求为 32 位。

编译器非常希望下一个项目从它正在编译的体系结构的自然字边界开始,以便可以通过单个操作读取下一个对象中的任何字段,而不是两个操作加上一些摆弄来组合两个不同的“词”。

【讨论】:

    【解决方案2】:

    结构体的uint32_t部分需要在4字节的倍数上对齐,所以结构体的大小必须是4字节的倍数才能保证结构体的数组不会出问题(错位访问问题 - 这可能导致某些机器上的 SIGBUS 错误以及(大多数)其他机器上(非常)低效的访问)。因此,编译器要求结构末尾有 2 个填充字节;这些没有名字,所以你不能合法地访问它们。

    【讨论】:

    • 是的,不是吗?它在一个 8 字节的 char 数组之后对齐。
    • 考虑一个包含 2 个项目的数组,每个 18 字节长。在索引为 0 的项目中,是的 - uint32_t 将位于 4 字节边界上。但是,在索引为 1 的项目中,偏移量将是 2 个字节的倍数,而不是 4 的倍数,所以这会失败……而不是让这种情况发生,GCC 添加了填充字节。注意(char *)&array[i+1] == ((char *)&array[i] + sizeof(array[i])).
    【解决方案3】:

    如果 gcc 使用 18 个字节来存储我的结构,为什么 sizeof 告诉我结构将占用 20 个字节?

    将 2 个这样的结构放入堆栈并为它们打印相同的内容,这会启发你。

    【讨论】:

    • 是的,gcc 将结构对齐到边界(在我的具体情况下,是 4 字节边界),但这不会改变 Pe_SymbolHeader 结构的大小。这在访问 PE 文件中的 Pe_SymbolHeader 等操作时很重要 (sizeof(Pe_SymbolHeader * symbol_index))
    【解决方案4】:
    uint32_t Value;
    

    这增加了 6 个字节,而不是预期的 4 个字节。我倾向于同意 Jonathan Leffler 关于根本原因的观点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-06
      • 2023-03-17
      • 2019-05-19
      • 2017-01-05
      相关资源
      最近更新 更多