知乎|嵌入式开发:MisraC—编写更安全、更清晰的C代码


知乎|嵌入式开发:MisraC—编写更安全、更清晰的C代码
【知乎|嵌入式开发:MisraC—编写更安全、更清晰的C代码】嵌入式开发人员经常抱怨没有一种编程语言适合他们的特殊需求 。 在某种程度上 , 这种情况并不令人惊讶 , 因为尽管许多开发人员都在开发嵌入式应用程序 , 但他们仍然只是世界编程社区的一小部分 。 尽管如此 , 有些语言的开发还是考虑到了嵌入式 。 值得注意的例子是PL/M、Forth和Ada , 它们都被广泛使用 , 但从未被普遍接受 。 其他语言 , 如Rust , 正在获得支持 , 但尚未成为主流 。 几乎被普遍采用的折衷方案是C , 如何使折衷方案最有效地发挥作用?
C语言结构紧凑 , 表达能力强 , 功能强大 。 它为程序员提供了编写高效、可读和可维护代码的方法 。 所有这些特性都是它受欢迎的原因 。 不幸的是 , 这种语言还使粗心大意的开发人员编写危险的、不安全的代码 , 这些代码在开发项目的所有阶段和部署中都可能导致严重的问题 。 对于安全性和/或安全性是主要优先事项的应用程序 , 语言的这些缺点是一个主要问题 。
正是在这种背景下 , 在20世纪90年代末 , 汽车工业软件可靠性协会(MISRA)推出了一套关于在车辆系统中使用C的指南 , 称为MISRAC 。 自那时以来 , 该指南一直在不断完善 , 并不时发布更新 。 还建立了类似的使用C++的方法 。 虽然该指南最初是针对汽车用软件的嵌入式开发人员 , 但很快就意识到 , 它们同样适用于安全性至关重要的许多其他应用领域 , 并且该标准现在已在许多行业中广泛采用 。
尽管MISRAC不是一个样式指南——事实上 , 许多用户应用了样式指南和标准——但许多规则也促进了清晰易读的可维护代码的编写 。 这是非常有益的 , 因为易于理解的代码不太可能隐藏细微的错误或未定义的行为 。
我将在这里简单介绍一下指南 。 MisraC正在不断地进行审查 , 不断地修改指南的清晰性和准确性 , 并支持更新版本的C语言标准 。 尽管细节发生了变化 , 但总体理念和方法没有变化 。
规则13.2–在所有允许的评估顺序下 , 表达式的值及其持续性副作用应相同
C语言标准在表达式的求值顺序方面为编译器提供了非常广泛的自由度 。 因此 , 在嵌入式开发中 , 任何对求值顺序敏感的代码都依赖于编译器 , 并且依赖于编译器的代码应始终被视为不安全的 。
规则17.2——职能部门不得直接或间接地调用自己
有时 , 表达算法的一种优雅方式是使用递归 。 但是 , 除非递归受到非常严格的控制 , 否则存在堆栈溢出的危险 , 这反过来会导致很难找到bug 。 在安全关键代码中 , 应避免递归 。
规则19.2–不应使用union关键字
尽管C是一种类型化语言 , 但类型化并不是很严格 , 开发人员可能会试图覆盖类型化来“简化”代码 。 遵守数据类型的约束对于创建安全代码至关重要 , 因为任何绕过数据类型的尝试都可能产生未定义的结果 。 union关键字可以用于多种目的 , 通常会导致代码不清晰 , 但也可以作为避免键入的一种手段 。
有人可能会争辩说 , 这些规则(以及MisraC的大部分 , 如果不是全部的话)只是常识 , 任何优秀的嵌入式开发人员都会采用这种方法 。 这可能是真的 , 但一套明确的指导方针让机会更少了 。