开发实践和工具可以防止编码错误

文章:马克理查森和安德鲁银行

嵌入式设计中的软件复杂性推动了对更好的开发实践和工具的需求,以避万博投注网址免编码错误

在过去十年中,应用尺寸和复杂性显着复杂。以汽车行业为例。根据纽约时报20年前,普通汽车有一百万行代码,但是10年后,通用汽车2010雪佛兰伏特有大约1000万行代码 - 超过F-35战斗机。今天,一辆普通汽车有超过1亿行代码。

向32位或更高的、具有大量内存和性能的处理器的转变,使公司能够在设计中构建更多的增值功能和能力;万博投注网址这是有利的一面。缺点是代码的数量及其复杂性常常导致影响应用程序安全性的故障。

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

  • 编码错误:示例是尝试访问数组的界限的代码。通过执行静态分析,可以检测这些问题。
  • 应用错误:只有通过确切知道该应用程序所做的操作,才能检测到这些,这意味着测试要求。

解决这些错误,设计工程师将长时间地沿着更安全和安全的代码的路径。

通过代码检查一盎司预防

代码中的错误发生在电子邮件和即时消息中的错误状态。这些是遇到的简单错误,因为工程师急于且不校对。但随着复杂性来说是一种造成巨大挑战的设计错误的色调。复杂性对系统如何运行的方式进行全新的了解,如何定义数据,以及如何定义值。是否错误是由复杂性或某种人类问题引起的,它们可以导致一段代码尝试访问数组范围之外的值。并且,编码标准捕获。

如何避免这样的错误?不要把它们放在首位。虽然这听起来很明显 - 近乎不可能 - 这正是编码标准带到桌子的价值。

在C和C ++世界中,80%的软件缺陷是由粗略或不适用于20%的语言引起的。编码标准对已知有问题的语言的部分创建限制。结果:避免了缺陷,软件质量大大增加。让我们来看看几个例子。

大多数C和C ++编程错误是由每种语言中固有的未定义,实现定义和未指定的行为引起的,这导致软件错误和安全问题。当符号整数移动右侧时,此实现定义的行为传播高阶位。根据编译器工程师使用,结果可以是0x40000000或0xc0000000,因为c未指定评估函数参数的顺序。

构造的代码示例行为依赖于所使用的编译器数字1某些C和C ++构造的行为取决于所使用的编译器。来源:LDRA

数字2- 在哪里rollDice ()函数只需读取包含值“1,2,3和4”的循环缓冲区的下一个值 - 预期的返回值将是1234.但是没有保证。至少一个编译器生成返回值3412的代码。

rolldice()函数的代码示例数字2某些C和C ++构造的行为由语言未指定。来源:LDRA.

C / C ++语言中有很多其他陷阱:使用构造等转到或者malloc;有符号值和无符号值的混合;或者“聪明的”代码,它可能非常高效和紧凑,但却如此神秘和复杂,以至于其他人难以理解。这些问题中的任何一个都可能导致缺陷,价值溢出突然变成负面的,或者仅仅使代码无法维护。

编码标准为这些疾病提供了一丝预防。它们可以防止使用这些有问题的构造,防止开发人员创建没有文档记录的、过于复杂的代码,以及检查样式的一致性。甚至像检查是否使用制表符或将圆括号放置在特定位置这样的事情都可以被监控。虽然这看起来很琐碎,但遵循这种风格可以极大地帮助手动代码审查,并防止在另一个编辑器中查看代码时由于不同的选项卡大小而引起的混乱——这些都是妨碍审查人员专注于代码的干扰。

MISRA来拯救我们

最着名的编程标准是Misra指导方针,首次于1998年发布汽车行业,现在通常由许多嵌入式编制者提供提供一些级别的屠杀检查。Misra侧重于C和C ++语言中的有问题的构建和实践,推荐使用一致的风格特征,同时停止缺乏建议。

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

MISRA规则5.4的快照数字3.这些MISRA C引用涉及未定义、未指定和实现定义的行为。来源:MISRA

大多数MISRA指导方针是“可决定的”,这意味着工具可以识别是否存在违反;但有些是“不可确定的”,这意味着工具不可能总是推断出是否存在违反。

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

2016年,MISRA增加了14条指导方针,以提供对安全关键代码的检查,而不仅仅是安全。图4.说明了一个新的指导方针-指令4.14解决了这个问题,并帮助防止陷阱由于未定义的行为。

MISRA指令的快照4.14数字4.MISRA指令4.14有助于防止由未定义的行为引起的陷阱。来源:MISRA

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

通过重新确保错误的错误,开发团队必须:

  • 减少大量调试的需要,
  • 更好地控制时间表,
  • 通过降低整体成本来控制投资回报率。

代码检查提供具有巨大潜在优势的工具箱。

一磅的固化和测试工具

虽然代码检查解决了许多问题,但只能通过测试产品确实应该做的内容,并且这意味着具有要求,只能找到应用程序错误。避免应用程序错误需要设计合适的产品,并设计产品。

设计合适的产品意味着在要求和源代码之间建立要求并确保双向可追溯性,从而实现了每个要求,并且每个软件功能都追溯到要求。任何缺失或不必要的功能 - 不符合要求 - 是应用程序错误。设计产品是确认发发系统代码满足项目要求的过程。通过执行基于要求的测试来实现这一点。

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

选择具有功能的双向可追溯性示例数字5.这是一个使用单个函数进行双向跟踪的示例。来源:LDRA.

图6.展示如何选择高级要求将上游可追溯性显示到系统级要求和下游,以低级要求和源代码功能。

选择需求的双向可跟踪性示例

数字6.这是需求选择的双向可跟踪性的一个例子。来源:LDRA.

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

测试代码功能要求了解应该做的内容,这意味着具有陈述每个功能的低级要求。图7.显示低级要求的示例,在这种情况下,它完全描述了单一函数。

描述单个函数的低级要求的代码示例数字7.这是描述单个函数的低级要求的示例。来源:LDRA.

测试用例源于低级要求,如图所示图8.

显示测试用例的表来自低级需求数字8.测试用例源于低级要求。来源:LDRA.

然后使用单元测试工具,然后可以在主机或目标上执行这些测试用例,以确保代码表现在要求时的要求。图9.表明所有测试用例都已回归和通过。

已经回归并通过的测试用例列表图9.这就是工具执行单元测试的方式。来源:LDRA.

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

编码中的新习惯

毫无疑问,软件复杂性 - 它的错误 - 具有连接,更快的内存,丰富的硬件平台以及特定的客户需求。采用最先进的编码标准,测量代码上的指标,跟踪要求和实现基于要求的测试,提供开发团队有机会创造高质量的代码并减少责任。

在没有标准要求对他们所带来的游戏变革的公司认可方面需要遵守诉讼时,团队的范围采用这些新习惯。采用这些实践,是否产品是安全或安全性的,可以对代码的可维护性和稳健性进行夜晚差异。清洁代码简化了新功能的添加,简化了产品维护,并使成本和安排到最低的所有特征,改善了公司ROI。

无论产品是否具有安全关键性,这肯定是一个只对开发团队有利的结果。

本文最初发布经济日报

马克理查森LDRA是铅现场应用工程师。

安德鲁银行是LDRA的技术专家和MISRA C工作组的主席。

相关文章:

发表评论