使用 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
的建议将提高您看到的性能,并消除由于缓冲区溢出引起的未定义行为
我得到了这个代码:
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
的建议将提高您看到的性能,并消除由于缓冲区溢出引起的未定义行为