1

考虑下面的程序,当程序执行时会发生什么?

 #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,结果应该是“strlen:1024”

但是我在 gcc 4.1 中执行它,结果是:

strlen:1024
segment fault

我想知道为什么会有段错误?

至少,如果应该有,为什么不在 read 系统调用中而是在 printf "stelen:1024" 之后立即抛出段错误?

任何帮助将不胜感激。

4

1 回答 1

3

看起来您愿意将 1024 字节复制到堆栈分配的 256 字节缓冲区中。这会导致未定义的行为任何事情都有可能发生。

在您的特定情况下,read()愉快地写入您的缓冲区并覆盖堆栈的一部分,包括当前执行函数的返回地址。直到main()尝试返回内存空间的未映射部分,然后您的程序出现段错误,才会发生太严重的事情。

另请注意,正如 wildplasser 在他的评论中正确指出的那样,看起来堆栈中被覆盖的部分仍然是零填充的,因此在索引处strlen()找到一个终止字符并且不会自行进入未映射的区域。\01024

当然,这种行为是完全不可靠的,如果你稍微修改你的程序,甚至在同一程序的运行之间,它可能会改变。

于 2013-04-07T09:44:57.690 回答