考虑下面的程序,程序执行时会发生什么?
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
main()
{
int fd;
char buf[256];
fd=open("/etc/passwd",O_RDONLY);
if(read(fd,buf,1024)<0)
printf("read fail\n");
printf("strlen%d:\n",strlen(buf));
}
我认为读取系统调用会将1024字节从内核缓冲区复制到buf,结果应该是&#34; strlen:1024&#34;
但我在gcc 4.1中执行它,结果是:
strlen:1024
segment fault
我想知道为什么会出现段故障?
至少,如果应该有,为什么不在读取系统调用中立即抛出段错误但是在printf&#34; stelen之后:&#34;?
任何帮助将不胜感激。
答案 0 :(得分:3)
看起来你愿意将1024个字节复制到堆栈分配的256字节缓冲区中。这导致undefined behavior。 任何事情都可能发生。
在您的特定情况下,read()
愉快地写入缓冲区并覆盖部分堆栈,包括当前正在执行的函数的返回地址。在main()
尝试返回到内存空间的未映射部分,然后程序段错误之前,没有太严重的事情发生。
另请注意,正如wildplasser在其评论中正确指出的那样,看起来被覆盖的堆栈部分仍然是零填充的,因此strlen()
在索引处找到终止\0
字符1024
并且不会漫游到未映射的区域。
当然,这种行为完全不可靠,如果您稍微修改程序,甚至在同一程序的运行之间,这种行为可能会发生变化。