C 为什么我在堆栈中启动的变量之间存在“间隙”?
我正试图处理缓冲区溢出的问题 当程序计数器到达ifmodified!=0,则基指针为0x00007FFFFFFFE0 在基指针的正下方,我看到4个字节包含有意义的整数0 但是,缓冲区不在修改的int的正下方 看起来像是4个字节的0,然后0x00007fff在堆栈中,然后我输入的64个字节紧跟其后 为什么字符缓冲区[64]不在int修改之后出现?为什么会有差距 我用gcc-g-fno堆栈保护器test1.c-o test1编译了它C 为什么我在堆栈中启动的变量之间存在“间隙”?,c,linux,stack,x86-64,buffer-overflow,C,Linux,Stack,X86 64,Buffer Overflow,我正试图处理缓冲区溢出的问题 当程序计数器到达ifmodified!=0,则基指针为0x00007FFFFFFFE0 在基指针的正下方,我看到4个字节包含有意义的整数0 但是,缓冲区不在修改的int的正下方 看起来像是4个字节的0,然后0x00007fff在堆栈中,然后我输入的64个字节紧跟其后 为什么字符缓冲区[64]不在int修改之后出现?为什么会有差距 我用gcc-g-fno堆栈保护器test1.c-o test1编译了它 首先,您应该了解,编译器/链接器可以自由地将任何地址分配给您在“自
首先,您应该了解,编译器/链接器可以自由地将任何地址分配给您在“自动”范围内声明的变量,即函数的本地变量,而main实际上只是另一个函数
至于为什么会有4个字节的“零”-这几乎可以肯定,因为在您使用的平台上,编译器知道对内存的访问效率更高,即当该内存的地址与8个字节的值对齐时,访问速度更快-因此它会“添加”额外的4个字节以适当地“对齐”缓冲区数组的地址。有关对齐和效率的讨论,请参阅。您已经有了一个大致的答案。特别是对于您的平台GCC/Linux/x86_64,相关的ABI System V x86-64指定大小为16字节或更大的数组始终至少16字节对齐。正如@AdrianMole在回答中所说,这是为了提高性能,特别是允许在阵列上使用SSE指令 请参阅System V x86-64 psABI 1.0版的第15页链接
如果使数组大小小于16字节,则不会发生这种情况。但是,还有一个GCC错误,它意外地将此规则应用于所有大于16位(即2字节)的数组。GCC 7.1已经解决了这一问题。您如何知道缓冲区从何处开始?因为计算机?如果没有一个非常具体的系统,讨论堆栈框架布局是没有意义的。大多数系统都有向下计数堆栈,但这并不一定相关。是的,linux x86_64 LinuxI在问题中添加了相关标记。
#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!");
}