这个结构的大小发生了什么?

时间:2016-03-13 22:30:43

标签: c struct

当我注意到这种古怪时,我正在研究C中的结构。

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

struct vulnStruct {
    char start[20];
    char overflow[10];
    char *controlledPointer;
};

int main(int argc, char *argv[]){
    struct vulnStruct *test = malloc(sizeof(struct vulnStruct));
    printf("Sizeof vulnStruct: %d\r\n", sizeof(struct vulnStruct));
    printf("Sizeof start: %d\r\n", sizeof(test->start));
    printf("Sizeof overflow: %d\r\n", sizeof(test->overflow));
    printf("Sizeof controlledPointer: %d\n\r", sizeof(test->controlledPointer));
    free(test);
    return 0;
}

编译时,此程序应输出vulnStruct及其元素的大小。手动添加结构表明它应该是38个字节长,但是当运行该程序时,它显示结构的大小是40个字节长。起初我认为它只是填充结构,如此回答(Size of a structure in C)但是,当我在结构的末尾添加一个2字节字段(uint16_t)以尝试填充填充时,它只是增加了struct 2个字节。这是因为控制编译器将controlledPointer填充到10个字节,并且不会让任何其他东西使用该空间,或者最后是占用空间的金丝雀。如果它只是填充,那么无论如何要安排元素,以便填充可以被另一个字段使用?

编辑: 如果我得到程序的输出也可能会有所帮助

Sizeof vulnStruct: 40
Sizeof start: 20
Sizeof overflow: 10
Sizeof controlledPointer: 8

提前致谢!

4 个答案:

答案 0 :(得分:2)

填充在溢出之间[10];和* controlledPointer。

问题在于它正在对字段进行4字节对齐 - 这几乎总是值得做的事情。对于非对齐内存访问,两个字节的内存几乎总是比时间代价便宜。

如果您尝试匹配某些其他结构或者您拥有大量商品,那么唯一会出现问题的情况就是这样。在这些情况下相应地声明它。不过,我的C太生锈了,无法告诉你如何宣布它。

答案 1 :(得分:0)

结构问题是他们有&#34;填充&#34;这意味着如果结构中有1个字符,则结构最多可能大小为4字节/ 8字节,具体取决于处理器的数据总线。这是因为为了优化访问速度,在编译结构时用0xff字节填充。

有些编译指令不使用填充但不建议这样做,除非您正在编写实际设备。这可以在gcc(默认的unix编译)中使用以下指令完成,但它取决于每个编译器:

#pragma (push,pack 1)
//define structure(...)
#pragma (pop)

在这种情况下,pragma有它自己的堆栈,如果你想要更清楚地了解填充和pragma指令,请查看this帖子

答案 2 :(得分:0)

请注意,每个目标/编译器的结果会有很大差异。

这是我在尝试专门了解有关填充的更多内容时得到的结果:

$ clang -Wpadded -Wno-format padd.c 
padd.c:10:11: warning: padding struct 'struct vulnStruct' with 2 bytes to align 'controlledPointer' [-Wpadded]
    char *controlledPointer;
          ^
1 warning generated.

这解释了哪个字段已经对齐以及出于什么原因。

答案 3 :(得分:0)

您的controlledPointer需要从address开始,这是8的倍数。

struct vulnStruct {
    char start[20];
    char overflow[10]; // 30 bytes
    // 30 is not a multiple of 8.
    // 2 bytes padding here
    // now controlledPointer starts at an address that is a multiple of 8
    char *controlledPointer; 
};