"The input/output library <stdio.h> shall not be used."

"The input/output library <stdio.h> shall not be used."

本文关键字:gt shall used be not lt input The output library stdio      更新时间:2023-10-16

我正在阅读JSF AV c++编码标准,规则22说:

AV规则22 (MISRA规则124,修订)

输入/输出库<stdio.h> 不得使用

有理由不使用<stdio.h>吗?

我知道这些规则是为 c++ ,我们可以使用<iostream>…但<stdio.h>有什么问题?

时不时会有这样的问题,为什么一些编码标准要求这样或那样。

正确的答案应该是:无论该编码标准的作者想要什么。有时候,编码标准给出了其规则的原因;这个显然不是。因此,我们只能猜测你的问题的答案可能是什么。

因此,我将添加我自己的猜测:

飞行器听起来是非常严肃的事情,具有极高的正确性和健壮性要求。printf, scanf等使编写代码变得容易,这些代码愉快地通过编译器,但在运行时产生未定义的行为。

比起普通的c++流,这些C函数确实有一个优势:格式字符串使编写国际化代码变得更容易。考虑下面这个快速创建的示例,使用std::ostream用于某些UI组件,例如客户管理应用程序中的按钮标签:
os << "Update customern";

你可能想动态地添加客户的名字:

os << "Update " << customer_name << "n";

您可能想要动态地为"Update"插入外文单词:

os << InternationalString(id_update) << " " << customer_name << "n";

然而,这本质上是以英语为中心的。它将生成正确的英语字符串,如"Update John"或"Update Joe",但对于德语将失败,因为德语具有不同的语法,并且需要像"John aktualisieren"或"Joe aktualisieren"这样的字符串,在这种情况下,名称在动词前面。

这是格式字符串的亮点所在:

sprintf(s, FormatString(id_update_customer), customer_name);

根据应用程序的语言设置,这样的FormatString函数可能返回"Update %s""%s aktualisieren"

不过,这还是很危险的。事实上,如果上面示例中的customer_namestd::string,那么您已经有未定义的行为了。

类库,如Boost。Format尝试将格式字符串的灵活性与流的类型安全性结合起来。

回到你的实际问题,我的猜测是,关于国际字符串的灵活性在飞行器业务中不是一个很大的问题。


正如您所看到的,可以对编码标准的每个方面进行很长的讨论。单个规则的原因可能并不总是那么明显,并且它们通常与编写标准的应用程序领域有关。

如果你不能问编码标准的作者,那么你的问题就不能真正得到回答。

最明显的问题是printfscanf以及它们的同类(例如sprintf)缺乏类型安全。

除了类型安全问题,scanfsprintf家族使得防止缓冲区溢出变得相当困难。这是可以做到的,但它不是微不足道的,似乎只有极少数的C程序员知道如何处理这类任务。

这个JSF c++标准引用了MISRA-C:1998,两者都与在安全关键系统中使用C 语言有关。最新的标准MISRA- c:2012已经更新(提供了更多的理由和更好的例子),MISRA规则124现在是规则21.6"不得使用标准库输入/输出函数"。

基本原理很简单:流和文件I/O有未指定的、未定义的和实现定义的行为。指南中还包括对C标准(C90和C99)部分的引用,其中描述了这些不可预测的行为。

如果实际实现定义良好或代码显示不重要,则可以打破规则(通过偏差过程)。