检查printf的返回值是否重要?

See*_*ddo 19 c

在我的一个大学项目中,我得到了积分,我的教授反馈说我没有处理printf错误.

用英语 - > / * ### FB: Error handling printf () is missing * /    

/* ### FB: Fehlerbehandlung printf() fehlt */
    printf("%7lu %8lld %10s %3lu %-8s %-8s %8lu %12s  %s %s %s\n",
           sb->st_ino, nblks, permstr, (unsigned long) sb->st_nlink,
           username, groupname, sb->st_size,
           ntime, filename, (symlink ? "->" : ""),
           (symlink ? symlink : "")
           );
Run Code Online (Sandbox Code Playgroud)

我的问题是,始终检查printf函数的返回值并处理错误是否非常重要?即使我发现错误,我仍然会fprintf用来打印stderr,我必须再次检查返回类型fprintf.

那么什么时候应该检查返回值,以及如何处理它?

dbu*_*ush 16

一般来说,您应该始终检查函数的返回值是否有错误.

在的情况下,printf然而,在大多数情况下,这样做没有什么用处.正如您所提到的,如果它确实失败了您可以使用fprintf打印到stderr,但那会引发一个问题,应该检查错误.

如果你没有重定向或重新打开,stderr你可能会遇到同样的问题,在这种情况下它可能没关系,但如果stderr指向其他地方,那么写那里可能有价值.您也可以退出该过程,但您需要确定这样做是否有意义.

您可能想要检查返回值的一个值得注意的时间是,您是否要跟踪为了格式化目的而打印的字符数.fprintf在写入日志文件以确定何时滚动日志时,我已经这样做了,但由于printf通常写入交互式控制台(如果不是由于重定向,你就不会知道它),那不会真的应用.

至于你的教授,我唯一的猜测是他希望你养成检查错误的习惯.这是一件好事,但是大多数规则都有例外,这就是其中之一.

  • @JohnBollinger printf系列函数有可怕的错误检查,可变参数列表可憎的事实使得这个讨论毫无意义.这就像是在争论为什么有人在将大象带到你的瓷器店之前没有清理它们的脚.使用不正确的格式说明符或错误的参数等的`printf`代码将在许多形式的UB中剧烈爆炸.它不会优雅地回归.此外,它不一定保证是可重入的.正确的解决方案是完全避免使用`stdio.h`,而不是试图抛光垃圾. (10认同)
  • 如果`printf()`失败了你能做什么?您可以中止线程或进程,在某些情况下这样做可能有意义.还有其他可能性.此外,如果您选择发出错误消息,这不一定是个坏主意,适当的流是`stderr`,并且没有理由假设仅仅因为`printf()`(到`stdout`)失败,`fprintf(stderr,...)`将无效. (8认同)
  • @TripeHound,相反,如果适用的指令要求识别和处理*all*错误,那么我认为没有理由排除`printf()`产生的错误.此外,我认为严格执行这样的约束有一些迂腐的价值,不是因为特别是细节'printf`,而是因为了解如何详细遵守规范的一般重要性.也有点促使人们认识到计算机没有做出那种暗示为`printf()`做出异常的价值判断这一事实. (3认同)
  • @Lundin一个不错的编译器会在编译时检查varadic参数是否已知格式字符串(何时不是?),因此如果使用-Wall -Werror进行编译,则永远不会出现这种UB (2认同)

chu*_*ica 11

为清楚起见 - printf()返回......

printf函数返回传输的字符数,如果发生输出或编码错误,则返回负值.C11§7.21.6.33


检查printf()负值的返回值是迂腐的,通常不需要.可以考虑以下情况:


环境限制.

一个单一的printf()"%s"可能超过环境极限,导致printf()返回一个负值.这并不意味着后续消息fprintf(stderr, ...也必须失败.

任何单次转换可以产生的字符数至少为4095.C11§7.21.6.115


输出设备薄弱.

情况stdout是知道要经常重新定向通过通信接口,其中输出故障需要检测.即使屏幕输出取得了非常高的成功,但对于串行(rs232)等各种其他输出流而言并非如此.在这种情况下stdout,stderr可以不同地重新定向,因此stderr可以保持可靠.


无论如何,如果教授在曲线上评分,很可能会有许多人产生相同的负值 - 所以没有年级差异.使用有奇怪要求和期望的客户.

  • 大多数情况下,当stdout是串行端口时,您将在断开连接时获得SIGHUP.为了将其转换为printf中的EIO错误,您需要显式忽略SIGHUP; 默认操作是终止进程,在适当的其他操作的应用程序中,安装信号处理程序是正常的.类似的观察也适用于SIGPIPE,另一种可能是stdout故障原因. (4认同)
  • 最后一句的`+(int)(M_PI/3)`.钉在棺材上. (2认同)