尝试运行优化的c文件时收到fgets警告

尝试运行优化的c文件时收到fgets警告,c,warnings,fgets,strtol,C,Warnings,Fgets,Strtol,这是一个大得多的文件的一部分,但这是唯一有问题的函数。问题是,如果我在gcc未优化的情况下编译它,我将得到我想要的一切,而不会出现问题。但是,如果我尝试将其编译为gcc-c-pg-02main.c, 我收到以下错误消息与任何其他输入函数一样,fgets可能由于各种原因而失败。从它的文档中可以找到,如果发生这种情况,它将返回NULL。但是,由于您不查看它的返回值,因此您永远不会知道。这正是编译器试图警告您的。如果失败,数组行将不包含有效的输入,并且可能包含垃圾,如果您试图处理它,可能会导致程序行为

这是一个大得多的文件的一部分,但这是唯一有问题的函数。问题是,如果我在gcc未优化的情况下编译它,我将得到我想要的一切,而不会出现问题。但是,如果我尝试将其编译为gcc-c-pg-02main.c,
我收到以下错误消息

与任何其他输入函数一样,
fgets
可能由于各种原因而失败。从它的文档中可以找到,如果发生这种情况,它将返回
NULL
。但是,由于您不查看它的返回值,因此您永远不会知道。这正是编译器试图警告您的。如果失败,数组
将不包含有效的输入,并且可能包含垃圾,如果您试图处理它,可能会导致程序行为异常

(在许多情况下,只有在启用优化时才会出现一些警告;这是因为编译器在优化过程中会对代码进行更详细的分析,这使它更有可能检测到此类问题。但这是一件好事;这不是优化的问题,也不是不使用它的原因。)

如果
fgets
失败,程序没有明显的恢复方法,因此最简单的方法就是退出并显示错误消息。
perror
函数是一种方便的方法;它打印一条与
errno
变量中的错误代码相对应的可读消息,该变量应设置
fgets

因此,这里错误检查的一种基本形式是将
fgets
行替换为:

if (fgets(line,MAX_LINE ,stdin) == NULL) {
    perror("Failed to read input");
    exit(1);
}
您可以在以后改进的一些事情:

  • fgets
    返回NULL的一个可能原因是文件结束:如果根本没有输入:用户在终端上按文件结束键(在Unix上通常为Ctrl-D,在Windows上为Ctrl-Z),或者从空文件重定向输入。这并不完全是一个错误,也不会导致
    errno
    中出现错误代码,因此在这种情况下
    perror
    可能会打印误导性消息。尝试修复此错误。您可以使用
    ferror
    功能区分这两种情况

  • 如果一行已成功读取,但无法解析为数字,
    strtol
    将失败。您当前也没有检查这一点。查看它是如何指示此故障的,并相应地进行处理


它给了您很好的建议:在使用
line
之前检查
fgets的返回值,以防函数出错。检查任何函数的返回值的方法与检查任何函数的返回值的方法相同。阅读手册页面,查看出错时返回的值,然后使用
if
条件检查该值:
if(fgets(line,MAX_line,stdin)=NULL){/*do error handling*/}
这是警告,不是错误。一个好的。在尝试使用读取的值之前,请始终检查输入函数是否成功。看不到什么?我发现很难相信在您添加错误检查以使用fgets的返回值之后,编译器仍然会发出警告。发布准确的更新代码,如果您声称该代码仍在发生,则发布该代码中的准确警告。您还应该向转换函数添加错误检查,如
strtol()
。如果你读到的不是整数怎么办?或者在一些前导数字后面有其他东西?@buckywucky:
strtol
不会通过其返回值来表示失败,而是通过其第二个
endptr
参数。所以你得看看它是怎么工作的。如果失败了,你自己决定怎么办。如果用户键入的内容不是数字,严格来说不是错误,只是误用,就会发生这种情况
peror
exit
可能不是最好的处理方法;您可能希望打印更自定义的消息,和/或让用户重试。