#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv) {
int modified;
char buffer[64];
modified = 0;
gets(buffer);
if(modified != 0)
printf("Changed!");
else
printf("Not changed!");
}
我在玩缓冲区溢出的游戏。
当程序计数器到达if(modified != 0)时,基本指针为0x00007fffffffdfe0。
在基本指针的正下方,我看到4个字节包含整数0,这是有意义的。
但是,缓冲区不在int修改之后。
它看起来像是4字节的0,然后0x00007fff在堆栈中,然后64字节,正如我随后输入的。
为什么char buffer64不在int修改之后出现呢?为什么会有“差距”?
我用gcc -g -fno-堆栈保护程序test1.c -o test1编译了它
谢谢
发布于 2020-01-30 07:33:44
你已经有了一个大致的答案。特别是对于您的平台(GCC/Linux/x86_64),相关的ABI (SystemVx86-64)指定大小为16字节或更大的数组总是至少对齐16字节。正如@AdrianMole在他的回答中所指出的,这是为了提高性能,特别是允许在数组上使用SSE指令。
请参阅系统Vx86-64 psABI版本1.0链接这里的第15页。
如果使数组大小小于16字节,则不会发生这种情况。然而,也有一个GCC错误意外地将此规则应用于所有大于16位的数组,即2字节。GCC 7.1已经修正了这一点。
发布于 2020-01-30 07:00:47
首先,您应该理解编译器/链接器可以为您在“自动”作用域中声明的变量(即函数的本地变量--而main
实际上是另一个函数)分配任意地址。
至于“为什么”存在‘0’的4个字节--这几乎可以肯定是因为,在您使用的平台上,编译器知道当内存的地址对齐到8字节值时,访问内存的效率更高(即更快)--因此它会添加‘额外的4个字节以适当地’对齐‘buffer
数组的地址。有关对齐和效率的讨论,请参见这里。
https://stackoverflow.com/questions/59988585
复制相似问题