当我注意到这种古怪时,我正在研究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
提前致谢!
答案 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;
};