【问题标题】:Getting fgets warning when trying to run optimized c file尝试运行优化的 c 文件时收到 fgets 警告
【发布时间】:2021-07-12 13:32:53
【问题描述】:

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

【问题讨论】:

  • 给你一个好建议:在使用line之前检查fgets的返回值,以防函数出错。
  • 检查任何函数的返回值的方法相同。阅读手册页以查看它在错误时返回的值,然后使用if 条件检查它:if (fgets(line,MAX_LINE ,stdin) == NULL) { /* do error handling */ }
  • 这是一个警告,而不是错误。和一个很好的。 总是在尝试使用读取的值之前检查输入函数是否成功。
  • 没看到什么?在您添加错误检查以使用 fgets 的返回值后,我很难相信编译器仍然会发出该警告。如果您声称它仍在发生,请发布该代码的确切更新代码和确切警告。
  • 您应该将错误检查添加到转换函数,如strtol()。如果你读到的不是整数怎么办?或者在一些前导数字之后还有其他东西?

标签: c warnings fgets strtol


【解决方案1】:

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

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

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

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

if (fgets(line,MAX_LINE ,stdin) == NULL) {
    perror("Failed to read input");
    exit(1);
}

一些你以后可以改进的地方:

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

  • 如果一行被成功读取但无法解析为数字,strtol 将失败。您目前也不检查。查看它如何指示此故障并进行相应处理。

【讨论】:

  • @buckywucky: strtol 不会通过它的返回值表示失败,而是通过它的第二个endptr 参数表示失败。所以你必须看看它是如何工作的。如果失败,您可以决定该怎么做。如果用户键入的内容不是数字,则可能会发生这种情况,严格来说这不是错误,只是误用。 perrorexit 可能不是最好的处理方式;您可能想要打印更自定义的消息,和/或让用户再试一次。
猜你喜欢
  • 2020-10-21
  • 2014-12-12
  • 2015-12-28
  • 2022-07-01
  • 1970-01-01
  • 2016-10-25
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
相关资源
最近更新 更多