【发布时间】:2013-08-30 12:16:43
【问题描述】:
我有一个简单的 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 个 bytes 位)。即使我在第一行用超过 1000 个字符的文本填充 ohai.txt,程序也不会出现段错误,我认为它会发生段错误,因为它溢出了由 output[] 数组指定的分配的可用空间量.
我的假设是操作系统会给程序额外的内存,同时它有额外的内存可供使用。这意味着程序只会在 ohai.txt 中的一行文本消耗的内存导致堆栈溢出时崩溃。
是否可以在 C 和内存管理支持方面有更多经验的人或反驳我关于为什么该程序不会崩溃的假设,即使文本文件的一行中的字符数远大于 256?
【问题讨论】:
-
你的假设是错误的。您应该仔细重新阅读
fgets的文档,尤其是它的第二个 /*parameter*/ 参数的意义。这应该会有所启发! -
会做...你的意思是第二个参数,确定吗?
-
@ironicaldiction 是的,第二个参数,肯定。
-
是的,争论 - 我不确定哪个术语在英语中是正确的
-
也 sizeof(char) == 1 根据 C 标准,在大多数系统上,char 是一个字节,而不是 4。其次,堆栈的工作方式不是你想象的那样。在这种情况下,在出现段错误之前,您必须使缓冲区溢出很多。基本上,您会为堆栈获得一定数量的页面,除非超出此范围,否则不会出现段错误,程序不会在每个函数调用上分配更多页面,因此整个可能的堆栈大小都是可写的。您的数组正在接近尾端,因此您可以在收到段错误之前最多写入几个堆栈帧