美国航天局的十大编码戒律(转)
美国航天局的十大编码戒律
Holzmann和团队在设计这些软件开发规则时,时刻谨记代码的安全问题。该规则明确写明是关于C语言的——C语言是NASA用于备份关键安全代码的支柱语言,有着悠久的历史和广泛的工具支持。不过,这些也可应用于其他大多数编程语言:
- 限制所有代码为简单的控制流结构——不使用goto语句,不使用setjmp和longjmp结构以及直接或间接的递归。
- 所有的循环必须有固定的上限。用检查工具静态地证明,预先设定的上限是一个循环不能超过的迭代次数,在数学上是可能的。如果循环限制不能静态证明,那么就违背了此条规则。
- 初始化后不要使用动态内存分配。
- 一个函数在标准参考格式下——每个语句一行,每个声明一行——得能印刷到同一张纸上。通常,这意味着每个函数的代码不超过60行左右。
- 代码的断言密度应平均为至少每个函数有两个断言。断言用于检查异常情况,在现实执行中是永远不会发生的。断言必须始终是无副作用的,并且被定义为布尔测试。如果断言失败,那就应该采取明确的恢复行动,例如,通过返回错误条件到执行失败断言的函数的调用者。对于任何断言,静态检查工具可以证明,它永远不会失败或从未违背此条规则(即,不可能通过增加无益的“assert(true)”语句来满足此条规则)。参见:《Developing NASA’s mission software with Java》
- 数据对象必须在尽可能小的范围内声明。
- 非空函数的返回值必须由每个调用函数进行检查,参数的有效性必须在每个函数内部进行检查。
- 使用预处理器必须仅限于包含头文件和简单宏定义。标记粘贴,变量参数列表,以及递归宏调用是不允许的。所有宏必须扩展到完整的语法单位。条件编译指令的使用通常也是靠不住的,但无法始终避免。这意味着,我们不应该超出标准样板,即使在大型软件开发中,也不应该有超过一个或两个条件编译指令,并避免多次包含相同的头文件。每一次使用条件编译指令都应该有正当理由,并在代码中通过基于工具的检查器标记。
- 指针的使用应当受到限制。具体地讲,解引用不允许超过一个级别。指针解引用操作可能无法隐藏在宏定义或内部定义类型声明。函数指针是不允许的。
- 从开发的第一天开始,所有代码都必须进行编译,并且所有的编译器警告应该在编译器最严谨的设置下开启。所有代码都必须在这些设置没有任何警告下进行编译。所有代码每日至少必须经过一台静态源代码分析器检查,当然最好能够不止一台,并在零警告下通过分析。
最后,正如Holzmann解释的那样:
如果你觉得这些规则看上去过于苛刻,那么请不要忘记,这是在NASA,你的生命可能就取决于它的正确性:代码要用来控制你飞的飞机,核能量与你住的地方可能只有几英里,或携带宇航员送入轨道的航天器。
这些规则正是这一行业所需的数字安全带——毕竟,生命之重重于泰山,否则将会带来一场浩劫……