亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial Internet of Things >> 嵌入式

培养新的编码习惯以减少嵌入式软件中的错误

在过去十年中,应用程序的大小和复杂性显着增加。以汽车行业为例。根据纽约时报 , 20 年前,普通汽车有 100 万行代码,但 10 年后,通用汽车 2010 雪佛兰 Volt 有大约 1000 万行代码——比 F-35 战斗机还多。今天,一辆普通汽车有超过 1 亿行代码。

转向具有大量内存和功率的 32 位及更高处理器使公司能够在设计中构建更多增值特性和功能;这就是好处。缺点是代码量及其复杂性通常会导致影响应用安全性和安全性的故障。

是时候采用更好的方法了。可以在软件中发现两种关键类型的错误,并使用防止引入错误的工具加以解决:

解决这些错误,设计工程师将在实现更安全可靠的代码的道路上任重而道远。

通过代码检查进行预防

代码中的错误与电子邮件和即时消息中的错误一样容易发生。这些是由于工程师匆忙而没有校对而发生的简单错误。但随着复杂性的出现,一系列设计错误会带来巨大的挑战。复杂性催生了对系统如何工作、数据如何传递以及值如何定义的全新理解水平的需求。无论错误是由复杂性还是某种人为问题引起的,它们都可能导致一段代码试图访问数组边界之外的值。并且,编码标准抓住了这一点。

您可能还对 Embedded 的这些相关文章感兴趣:

使用 MISRA C/C++ 构建安全可靠的嵌入式系统

使用静态分析检测开源安全关键服务器应用程序中的编码错误

如何避免此类错误?首先不要把它们放在那里。虽然这听起来很明显——而且几乎不可能——但这正是编码标准带来的价值。

在 C 和 C++ 世界中,80% 的软件缺陷是由于对大约 20% 的语言的不正确或不明智的使用造成的。编码标准对已知有问题的语言部分进行了限制。结果:避免了缺陷,软件质量大大提高。我们来看几个例子。

大多数 C 和 C++ 编程错误是由每种语言固有的未定义、实现定义和未指定的行为引起的,这些行为会导致软件错误和安全问题。当有符号整数右移时,此实现定义的行为会传播高位。根据编译器工程师使用的不同,结果可能是 0x40000000 或 0xC0000000,因为 C 没有指定计算函数参数的顺序。


图 1. 某些 C 和 C++ 构造的行为取决于所使用的编译器。资料来源:LDRA

在图 2 中——rollDice() 函数只是从包含值“1,2,3 和 4”的循环缓冲区中读取下一个值——预期的返回值将是 1234。但不能保证这一点。至少有一个编译器生成返回值 3412 的代码。


图 2. 某些 C 和 C++ 构造的行为未由语言指定。资料来源:LDRA

C/C++ 语言中还有许多其他陷阱:使用诸如 goto 之类的结构 或 malloc;有符号和无符号值的混合;或“聪明”的代码,它们可能高效且紧凑,但又是如此神秘和复杂,以至于其他人难以理解。这些问题中的任何一个都可能导致缺陷、突然变为负值的值溢出,或者只是使代码无法维护。

编码标准为这些疾病提供了预防措施。它们可以防止使用这些有问题的构造,并防止开发人员创建未记录的、过于复杂的代码以及检查样式的一致性。甚至可以监视诸如验证未使用制表符或括号是否位于特定位置之类的事情。虽然这看起来微不足道,但遵循这种风格极大地有助于手动代码审查,并防止在另一个编辑器中查看代码时由不同的标签大小引起的混淆——所有这些干扰都会阻止审查者专注于代码。

MISRA 来救援

最著名的编程标准是 MISRA 指南,该指南于 1998 年首次发布用于汽车行业,现在被许多提供某种程度的 MISRA 检查的嵌入式编译器普遍采用。 MISRA 专注于 C 和 C++ 语言中存在问题的构造和实践,建议使用一致的风格特征,同时不建议任何。

MISRA 指南提供了有关为什么每个规则存在的有用解释,以及该规则的各种例外的详细信息,以及未定义、未指定和实现定义的行为的示例。图 3 说明了指导水平。


图 3. 这些 MISRA C 引用与未定义、未指定和实现定义的行为有关。资料来源:LDRA

大多数 MISRA 指南都是“可判定的”,这意味着该工具可以识别是否存在违规行为;但有些是“不可判定的”,这意味着该工具并不总是可以推断出是否存在违规行为。

如果静态分析工具无权访问系统函数的源代码,则传递给应初始化它的系统函数的未初始化变量可能不会注册为错误。有可能出现假阴性或假阳性。

2016 年,MISRA 中添加了 14 条准则,以提供对安全关键代码的检查,而不仅仅是安全性。图 4 说明了其中一项新指南 - 指令 4.14 - 如何解决这个问题并帮助防止由于未定义行为而导致的陷阱。


图 4. MISRA 指令 4.14 有助于防止由未定义行为引起的陷阱。资料来源:LDRA

严格的编码标准传统上与汽车、飞机和医疗设备等关键应用的功能安全软件相关。然而,代码的复杂性、安全性的重要性以及创建易于维护和升级的高质量、健壮代码的业务重要性使得编码标准在所有开发操作中都至关重要。

通过确保首先不会在代码中引入错误,开发团队必须:

代码检查提供了一个具有巨大潜在好处的工具箱。

用测试工具一磅治愈

虽然代码检查解决了很多问题,但只有通过测试产品是否完成了它应该做的事情才能发现应用程序错误,这意味着有需求。避免应用程序错误既需要设计正确的产品,也需要正确设计产品。

设计正确的产品意味着预先建立需求并确保需求和源代码之间的双向可追溯性,从而实现每一个需求,每个软件功能都追溯到一个需求。任何缺失或不必要的功能(不满足要求)都是应用程序错误。产品设计权是确认开发的系统代码满足项目要求的过程。您可以通过执行基于需求的测试来实现这一目标。

图 5 显示了双向可追溯性的示例。选择的单个功能从功能上溯到低级需求,然后到高级需求,最后到系统级需求。


图 5. 这是一个选择单个功能的双向可追溯性示例。资料来源:LDRA

图 6 显示了选择高级需求如何显示上游到系统级需求和下游到低级需求和源代码功能的可追溯性。


图 6。这是选择了需求的双向可追溯性示例。资料来源:LDRA

这种可视化可追溯性的能力可以在生命周期的早期检测应用程序错误。

测试代码功能需要了解它应该做什么,这意味着具有说明每个功能做什么的低级要求。图 7 显示了一个低级需求的示例,在这种情况下,它完全描述了单个功能。


图 7。这是描述单个功能的低级需求的示例。资料来源:LDRA

测试用例源自低级需求,如图 8 所示。


图 8. 测试用例源自低级需求。资料来源:LDRA

使用单元测试工具,然后可以在主机或目标上执行这些测试用例,以确保代码按照需求所说的方式运行。图 9 显示所有测试用例均已回归并通过。


图 9. 这是工具执行单元测试的方式。资料来源:LDRA

一旦运行了测试用例,就应该测量结构覆盖率以确保所有代码都得到了执行。如果覆盖率不是 100%,则可能需要更多的测试用例或应该删除多余的代码。

编码的新习惯

毫无疑问,软件复杂性及其错误随着连接性、更快的内存、丰富的硬件平台和特定的客户需求而迅速增加。采用最先进的编码标准、衡量代码指标、跟踪需求并实施基于需求的测试,为开发团队提供了创建高质量代码和减少责任的机会。

当没有标准要求合规时,团队采用这些新习惯的程度取决于公司对它们带来的游戏规则变化的认可。采用这些实践,无论产品是安全关键还是安全关键,都可以在代码的可维护性和健壮性方面产生昼夜变化。干净的代码简化了新功能的添加,简化了产品维护,并将成本和进度保持在最低水平——所有这些特性都可以提高贵公司的投资回报率。

无论产品是否安全,这肯定是对开发团队有利的结果。

>> 本文最初发表于我们的姊妹网站 EDN。


嵌入式

  1. 文本字符串是嵌入式软件中的漏洞吗?
  2. 嵌入式边缘的 SOAFEE 架构支持软件定义汽车
  3. Pixus:用于嵌入式电路板的新型厚实而坚固的面板
  4. 控创:新的嵌入式计算标准 COM HPC
  5. congatec 推出 10 个新的嵌入式边缘计算高端模块
  6. congatec:用于能源领域的新型嵌入式边缘服务器技术
  7. GE Digital 推出新的资产管理软件
  8. 如何不沉迷于教授新软件
  9. 软件风险:保护物联网中的开源
  10. 保护软件供应链的三个步骤
  11. Saelig 发布由 Amplicon 制造的新型嵌入式 PC
  12. 使用 DevOps 解决嵌入式软件挑战