[英]How come my C program doesn't crash when I overflow an allocated array of characters?
我有一个简单的C文件I / O程序,它演示了逐行读取文本文件,并将其内容输出到控制台:
/**
* simple C program demonstrating how
* to read an entire text file
*/
#include <stdio.h>
#include <stdlib.h>
#define FILENAME "ohai.txt"
int main(void)
{
// open a file for reading
FILE* fp = fopen(FILENAME, "r");
// check for successful open
if(fp == NULL)
{
printf("couldn't open %s\n", FILENAME);
return 1;
}
// size of each line
char output[256];
// read from the file
while(fgets(output, sizeof(output), fp) != NULL)
printf("%s", output);
// report the error if we didn't reach the end of file
if(!feof(fp))
{
printf("Couldn't read entire file\n");
fclose(fp);
return 1;
}
// close the file
fclose(fp);
return 0;
}
看起来我已经为每行分配了一个空间为256个字符的数组(32位机器上的1024
字节
位)。 即使我在第一行填写的文本超过1000个字符的ohai.txt
,程序也不会出现段错误,我认为它会溢出,因为它溢出了output[]
数组指定的可用空间。 。
我的假设是操作系统会为程序提供额外的内存,同时它有额外的内存可用。 这意味着只有当ohai.txt
的一行文本占用的内存导致ohai.txt
时,程序才会崩溃。
有更多C和内存管理经验的人是否支持或反驳我的假设,即为什么这个程序不会崩溃,即使文本文件的一行中的字符数远大于256?
你不会在这里溢出任何内容: fgets
不会向sizeof(output)
字符写入缓冲区,因此不会溢出任何内容(参见文档 )。
但是,如果溢出缓冲区,则会出现未定义的行为。 根据C规范,程序可能会做任何事情 :崩溃,不崩溃,无声地破坏重要数据,意外调用rm -rf /
等等。因此,如果调用UB,不要指望程序崩溃。
OP的程序没有崩溃,因为没有缓冲区溢出发生。
while(fgets(output, sizeof(output), fp) != NULL)
printf("%s", output);
fgets()
很好地读取一组char
到一个或255或一个\\n
的计数。 然后printf("%s" ...
很好地将它们打印出来。重复这一过程,直到没有更多的数据/
没有崩溃,没有溢出,没有运行,没有命中,没有错误。
fgets(output,sizeof(output),fp)读取(sizeof(输出)-1)这种情况下的字符数(否则读取直到换行符或文件末尾)
堆栈的解释以及为什么即使你实际上溢出也不会发生段错误(并且正如其他人已指出所写的代码不会)
你的堆栈指针从某个地址开始,比如说0x8000000,然后运行时调用main,它会向下移动一点(可能还有其他的东西,所以我们不知道在main的开头有多少东西在堆栈上),然后main将为所有它的局部变量移动堆栈指针。 所以在这一点上你的数组将有一个低于0x8000000超过256字节的地址,除非你在所有main的堆栈帧和任何其他C运行时东西的堆栈帧上运行,否则你不会得到段错误。
因此,为了简单起见,假设您的数组最终得到的是0x7fffd00的基地址,即低于0x8000000的768字节,这意味着至少你必须溢出那么多以获得段错误(好吧,你可能会遇到段错误)主要返回或当你调用feof时,因为你用随机字符填充你的堆栈框架,但是我们正在讨论fgets()中的段错误,但即使那些可写的东西被映射到堆栈上方的页面也是如此(不太可能是大多数操作系统)避免这样做,这样如果你溢出得足够远,你会得到一个段错误)
如果堆栈以另一种方式运行(即:向上增长),则必须运行整个最大大小的堆栈,在用户空间中通常非常大(Linux上的默认值为32位x86是2MB)但我很漂亮确保x86堆栈向下增长,这样你的情况就不太可能了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.