我是我的大学的计算机科学实验室的实验助理,在第一周的课程中,一个学生显示了以下代码:
#include <stdio.h>
#include <stdlib.h>
static void copy (FILE *, FILE *);
int main (int argc, char *argv[])
{
copy (stdin, stdout);
return EXIT_SUCCESS;
}
static void copy (FILE *input, FILE *output)
{
char c[2];
while(fgets(c, 5, input) != NULL) {
fputs(c, output);
}
}
以上示例中的代码的工作原理似乎是将五个字符读入大小为2的char数组中没有问题,但是一旦在stdin中达到EOF,就会导致分段错误。 < / p>
我们正在学习还使用各种输入和输出函数,他们发现此代码具有奇异的功能。
当fgets尝试将更多的字符读入变量'c'时,您会期望(或者我会认为)某种错误,
但是,此代码的执行完全像是怀疑一个相同功能的程序正常运行(回显输入到标准输入中的字符),然后在键入EOF字符后在后出现段错误。可以通过在每个换行符之间仅键入n-2个或更少的字符来防止这种分段错误,但始终会在键入EOF字符后触发(无论先前键入了多少行)。
为什么会这样?似乎我的程序一直等到程序结束时才告诉我它在二十行输入之前出现了分段错误!
答案 0 :(得分:3)
由于草率的编程,这是缓冲区溢出的一个简单经典案例。 缓冲区溢出会导致不确定的行为。
...
char c[2]; // your declare your array with 2 elements
while(fgets(c, 5, input) != NULL) { // but here you pretend it has 5 elements
fputs(c, output);
...
您想要这个:
...
char c[2]; // btw 2 is execcsively small anyway
while(fgets(c, sizeof c, input) != NULL) { // use correct size of c here
fputs(c, output);
...
未定义的行为确切地意味着:行为未定义,任何事情都可能发生,包括: