使用 C 中的 fgets() 函数检测到堆栈粉碎

Stack smashing detected with fgets() function in C

我得到了这个代码:

while(!feof(fp))
{
   fgets(line,20,fp);
   puts(line);
}

fp 是这个文件:

prova1
prova2
prova3prova4
prova5

事实是:如果 fgets 函数的计数参数小于 10,则一切正常,但如果大于 10,则会出现 stack smashing detected 错误。

我认为这是因为我试图在 EOF 之后阅读,但为什么当我试图在它工作后立即阅读时(比如每行 8 个字符)但是当我输入一个像 20 的计数参数时它给出了我出错了?

注意: 最后一行 "prova5" 由 6 个字符加上我认为的 '\0' 组成,所以是 7。为什么 8 可以,但不行用 20?

编辑: 对不起,我忘了包括这个声明:

char line[] = " ";

为什么8个可以,20个不行?

这表明 line 可能没有定义足够的 space 来包含 20 char。为了与您的代码片段一致,line 应定义为:

char line[20];  

根据您对 line 的实际定义,您可能会看到 buffer overflow. The reason it seems to work, then not work is undefined behavior 的结果,这意味着任何行为都是可能的,而且是在意想不到的时候。

此外,您应该考虑将 while(!feof(fp)) 替换为 while(fgets(line, 20, fp)),它检查 fgets 的 return 作为测试,并在看到 NULL 时退出。 feof() (is broken)

while(fgets(line, 20, fp))//will exit loop upon a null return
{
   //do something with line;
   puts(line);
}  

编辑 以解决评论中的说明:

如果您将 line 声明为指针:

字符*行;

然后在您的其余代码中使用它之前,需要为指针提供一个地址,该地址具有足以包含 20 char 的相应内存。此语句(以及确保内存已分配的测试)将同时执行:

line = calloc(20, 1);
if(line)
{
    //use line as described above  

编辑 2 以解决 OP 中的新信息。

因为line被定义为(后来编辑成OP)

char line[] = " ";

它只能容纳 1 个字符。此 导致 buffer overflow,并解释了观察到的不一致行为(并在 post 中进行了描述)

定义 line 以支持 post 中显示的代码需要的建议方法是:

char line[20] = {0}; //space for 20 char, initialized to all zeros.

这个连同其他关于用 fgets 替换 feof 的建议将提高您看到的性能,并消除由于缓冲区溢出引起的未定义行为