汽车软件系统C语言开发指南

C语言比C++更简洁、执行效率更高、代码量更小,因此在汽车的小控制部件中被广泛使用。MISRA致力于协助汽车 厂商开发安全可靠的软件的跨国协会,其成员包括了全球一些汽车公司、汽车零部件供应商和高校等研究机构,如:宾利汽车、福特汽车、捷豹汽车、TRW 汽车电 子、利兹大学等。MISRA-C针对国际标准化组织(International Organizati on of Standardization,ISO)中C语言在关键嵌入系统中的不安全性进行了补充说明和要求。

一、MISRA-C规范

MISRA-C先后推出了MISRA-C:1998、MISRA-C:2004、MISRA-C:2012编程规范。MISRA-C:2012将编程的安全性规范包含16条指令和143规则。指令是一种不可能提供执行合规检查所需的完整描述的指导方针,指令需要额外的辅助信息(设计文档、需求规范)和工具(静态分析)才能完成代码的合规性检查。MISRA-C:2012包含9条需要性和7条建议性的指令。规则是对已经提供完整描述需求的指导方针,可以不需要其他任何信息来检查源代码是否符合规则。MISRA-C:2012包含10条强制性规则、32条推荐性规则和101条必需性规则。
与MISRA-C:2004相比,MSRA-C:2012规则分类增加了未使用代码、资源和重叠存储。删除了语言外延,规则也由原来的两类分成三类:必需规则、强制规则、推荐规则。

二、MISRA-C 对安全性的理解

MISRA-C主要针对汽车,但不仅限于在汽车软件开发上使用,还可以用在其他一些安全相关的关键嵌入式系统。MISRA-C:2012对程序设计中存在的风险从以下4个方面进行控制:语言本身存在的未定义、程序员的失误、程序员对语言和编译器的误解、运行出错。

1. C语言本身存在的定义问题

ISO标准并没有完全指定语言,而是有意将某些方面置于实现的控制之下。部分原因是希望为完全不同的目标处理器支持许多已存在的实现(Implementations)。这能够增加C语言在编程和编译时的灵活性,但也带了潜在的不安全风险。

在C标准中没有做明确规定的地方会用、未指定(Unspecified)、未定义(Undefined)或实现-定义(Implementation-defined)来表述。

未指定行为(Unspecified behavior):ISO标准提供了两种或多种可能性并且在任何情况下都没有强加进一步要求的行为。编译器往往有几种可选的处理方式,C标准没有明确规定按哪种方式处理,编译器可以自己决定,并且也不必写在编译器的文档中, 同一个编译器的不同版本来编译也可能得到不同的结果,因为编译器没有在文档中明确写它会怎么处理。因此,不同版本的编译器也可以选择不同的处理方式。

未定义行为(Undefined behavior):在使用不可移植或错误程序结构或错误数据时的行为,ISO标准里没有对该行为的的要求。C标准没规定怎么处理,编译器很可能也没规定,甚至也没做出错处理,有很多Undefined的情况编译器是检查不出来的,最终会导致运行时错误,比如数组访问越界。

实现-定义行为(Implementation-defined behavior):每个实现都记录了如何做出选择的未指定行为。 C标准没有明确规定char是有符号的还是无符号的,但是要求编译器必须对此做出明确规定,并写在编译器的文档中。编译器可以定义char型是无符号的,也可以定义char型是有符号的,在该编译器所对应的体系结构上哪种实现效率高就可以采用哪种实现,这是C语言中典型的Implementation Defined行为。char和unsigned char都作为字符用的话是没有区别的,但当整数用时有区别,char 整数范围为-128到127( 0x80-0x7F),unsigned char 整数范围为0到255( 0-0xFF )。C语言Implementation Defined的特性与平台和编译器是密不可分,在vc和x86平台上,gcc编译器定义char型是有符号的,而arm嵌入式系统的 arm-linux-gcc 编译器却把 char 定义为 unsigned char。与平台和编译器的密切关联就会出现代码移植上的问题。而C标准这样做的根本原因之一是:优先考虑效率,其次考虑移植性。如果程序员要写可移植的代码,就必须清楚哪些写法是不可移植的,应该避免使用。另一方面,不考虑移植性的问题时,写不可移植的代码有时候也是必要的,比如Linux内核代码使用了很多只有gcc支 持的语法特性以得到最佳的执行效率,因为这些代码具有固定的编译器编译。

在实际编程中,这些与平台、编译器密切相关的操作,程序员在编写车载软件时,必需考虑代码的移植安全,尽可能的避免使用实施-定义行为的C语言编程,从而规避潜在的风险。MISRA-C通过禁止一些实施-定义、未定义、未指定的的编程行为来防范潜在的安全风险。

例如,MISRA-C:2012的规则11.6:不应在指向 void 的指针和算术类型之间执行强制转换。

void * p;
uint32_t u;
p = ( void * ) 0x1234u; /* 不合规 – 实施定义 */
p = ( void * ) 1024.0f; /* 不合规 – 未定义 */
u = ( uint32_t ) p; /* 不合规- 实施定义*/ 

毫无疑问,ISO-C无法直接被应用在关键的软件系统开发中,而MISRA-C作为ISO-C标准的一个衍生版本,为了安全性,限制了C语言的部分灵活性。

2. 程序员失误

虽然C语言程序可以以一种结构化和可理解的方式进行布局,但C语言使程序员很容易编写难以理解的模糊代码。运算符的规范使得编译器很难检测到编程错误。 例如,以下两段代码都是完全合法的,因此编译器不可能知道其中一个是否被错误地用来代替另一个:

if ( a == b )    /* 测试a和b是否相等*/
if ( a = b )     /* 将b赋值给a,并测试a是否不为零 *

3. 程序员对语言和编译器的误解

程序员通常会误解该语言的某些领域。 例如,C 比其他一些语言有更多的运算符,因此有大量不同的运算符优先级,其中一些不直观。例如,规则13.3:包含递增 (++) 或递减 (–) 运算符的完整表达式除了由递增或递减运算符引起的副作用外,不应有其他潜在副作用。

u8a = ++u8b + u8c-;   //不合规

上述表达式应写成如下更清楚的表达方式:

++u8b;
u8a = u8b + u8c;
u8c--;   //合规

C 提供的类型规则也会让熟悉强类型语言的程序员感到困惑。 例如,操作数可能被“提升”为更广泛的类型,这意味着操作产生的类型不一定与操作数的类型相同。例如:

uint16_t u16a = 40000; /* unsigned short 或 unsigned int ? */
uint16_t u16b = 30000; /* unsigned short 或 unsigned int ? */
uint32_t u32x; /* unsigned int 或unsigned long ? */
u32x = u16a + u16b; /* u32x = 70000 or 4464 ? */

预期的结果可能是 70000,但分配给 u32x 的值将取决于 int 的实现大小。 如果int实现大小是 32 位,则加法将发生在 32 位有符号算术中,并且将获得“正确”的值。如果它只有 16 位,则加法将在 16 位无符号算术中进行,将发生回绕并将产生值 4464 (70000 % 65536)。 无符号算术中的回绕定义明确,但由于其效果取决于执行算术的类型,因此其有意使用应当被记录。

编译器可能会提供一些C语言的扩展,开发人员如果不了解而编译器开发人员提供的关于编译器缺陷列表及任何可用的变通方法,则可能无法确认编译器是否符合ISO C的规范,也不知道编译程序所需的资源(时间,内存等),从而忽略了编译器暴露的缺陷。这种不安全的行为主要是由程序员对编译器的不了解造成的对编译、执行的误解。

4. 运行出错

C 程序可以编译成小而高效的机器代码,但代价是运行时检查的程度非常有限。 C 程序通常不为常见问题提供运行时检查,例如算术异常(例如被零除)、溢出、指针的有效性或数组绑定错误。 C 哲学是程序员负责明确地进行此类检查。但是往往程序员的检查环节缺失时,这些运行时的问题将会给程序造成极大的安全隐患。MISRA-C为了尽量避免这种情况发生,提供了具有广泛指导意见的规范,例如,指令4.1:运行错误应当最小化。
算术错误示例:

float32_t f1 = 1E38f;
float32_t f2 = 10.0f;
float32_t f3 = 0.1f;
float32_t f4 = ( f1 * f2 ) * f3; /* (f1 * f2) 将要溢出 */
float32_t f5 = f1 * ( f2 * f3 ); /* 没有溢出,因为(f2 * f3) 是近似为 1 */
if ( ( f3 >= 0.0f ) && ( f3 <= 1.0f ) )
{f4 = f3 * 100.0f; /* 没有溢出,因为 f3 已知的范围是在0到1 ,所以乘法的 * 结果将适合 float32_t 类型 */
}

除检查算术错误外,指针算术、数组边界错误、函数参数、指针复引用(或解引用)、动态内存都是程序员要进行的动态检查的领域。

总结

MISRA-C:2012已经能够覆盖标准C编程规范的99%的规则。MISRA-C规范中的指令和规则已经能够很好的帮助程序员和研究人员开发出符合规范的车载软件。

除了上述列举的示例,MISRA-C的规范需要进一步的深入解读,才能在车载软件产品开发过程中规避软件安全风险,本文只是做一个简单的概括性的解读。随着智能车辆的发展,无人驾驶系统中的车辆感知、控制、路径规划完全依靠程序完成,软件系统的安全性就变得尤为重要。作为算法开发工程师、无人驾驶系统工程师、产品经理,完全掌握MISRA-C,对于开发出更安全的智能驾驶车辆尤为重要。

第七十六篇:车辆安全-车载软件C语言开发指南(MISRA-C)相关推荐

  1. 第七十七篇:车辆安全-车载软件C++语言开发指南(AUTOSAR C++)

    C++是面向对象的编程,比C语言更加复杂,抽象程度高,但C++在一些图像处理.系统.控件的编程方面,实用性更强,具有自己的编程优势.在车载嵌入式系统的开发中,C和C++都具有重要的作用.C++语言所使 ...

  2. “约见”面试官系列之常见面试题之第七十六篇之vue-router中的路由钩子函数基本用法 (建议收藏)

    vue-router中的路由钩子函数基本用法 路由钩子函数分为三种类型如下: 第一种:全局钩子函数. router.beforeEach((to, from, next) => { consol ...

  3. C语言/C++常见习题问答集锦(七十六)之玫瑰花寄语

    C语言/C++常见习题问答集锦(七十六)之玫瑰花寄语 程序之美 在古希腊神话中,玫瑰花集爱与美于一身,既是美神的化身,又溶进了爱神的血液.可以说,在世界范围内,玫瑰是用来表达爱情的通用语言,形成了永不 ...

  4. 七十六、Python | Leetcode二分查找和分治算法系列

    @Author:Runsen @Date:2020/7/4 人生最重要的不是所站的位置,而是内心所朝的方向.只要我在每篇博文中写得自己体会,修炼身心:在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰 ...

  5. 秒杀多线程第十六篇 多线程十大经典案例之一 双线程读写队列数据

    本文配套程序下载地址为:http://download.csdn.net/detail/morewindows/5136035 转载请标明出处,原文地址:http://blog.csdn.net/mo ...

  6. CCIE-LAB-第十六篇-NAT+OSPF下发默认路由+校验配置(模块一结束篇章)

    CCIE-LAB-第十六篇-NAT+OSPF下发默认路由+校验配置(模块一结束篇章) 实际中,思科只会给你5个小时去做下面的全部配置 这个是CCIE-LAB的拓扑图 问题 翻译: 根据这些要求1为FA ...

  7. CCNA-第十六篇-综合实验

    CCNA-第十六篇-综合实验 环境以及拓扑图如下 TAG:个人说明,做到最后我才发现hostname打错了,IDC-1打成ISP-1了,不过也没关系,知道就行了,全部的IDC都打成ISP了 还有一个的 ...

  8. java监听数据库操作_第十六篇——JDBC操作数据库之监听器

    JavaWeb应用中,很多的地方都和session有关.因此session相关的事件监听器,在日常工作中非常有用. 有时候我们需要统计当前在线的人数和访问人数总数,此时就可以使用监听器技术来很简单的实 ...

  9. JavaScript学习(七十六)—this的指向问题

    JavaScript学习(七十六)-this的指向问题 在文档中(全局环境中)直接使用this,代表的是window 在HTML事件处理程序中,如果将this作为实参传递给事件处理函数,this代表的 ...

最新文章

  1. R语言ggplot2可视化为组合图添加综合图例实战:使用ggpubr包ggarrange函数实现综合图例、使用patchwork包实现综合图例
  2. RxJava 和 RxAndroid 五(线程调度)
  3. 微信开放平台,微信登陆第三方网站 提示redirect_uri 参数错误
  4. 天下会 - 搜索实战系列之视频
  5. 《Linux内核分析》第一周笔记 计算机是如何工作的
  6. ant design datepicker处理日期范围操作
  7. 开篇词:如何轻松获得 Offer
  8. java中怎么删除多表连接_在Java中从多个列表中合并和删除重复的最佳方式
  9. 二叉树的基本操作(建立与遍历)
  10. Java: Number转换为BigDecimal:最好方法
  11. OpenCV读图、展示和保存新图
  12. GTK 3.0弹出窗口及设置背景图片的代码
  13. 2021-09-18
  14. (Python)实现对非人脸图片的清洗
  15. 服务器网站中断,如何解决无法打开网页及服务器已断开连接的问题?
  16. var/let/const、块级作用域、TDZ、变量提升
  17. 视频合并软件怎么把多个视频合并为一个视频
  18. 8月顺利拿到OPPO公司Android架构师offer,一面+部长面
  19. 2022华为软挑比赛(初赛笔记)
  20. 四极管:WaitForMultipleObjects的疑惑

热门文章

  1. SpringCloud 教程 (二) 服务链路追踪(Spring Cloud Sleuth)
  2. 机器人参加高考还拿高分,究竟怎么做到的?
  3. web页面 新消息提示音
  4. 无线传感网的MAC层协议
  5. 【转载】2019 年,国内博士后的招聘要求和待遇是怎样的?
  6. 三星android怎么解锁,三星S7解锁教程_三星S7怎么Bootloader解锁(附教程)_玩游戏网...
  7. 手写一个垂直领域的搜索引擎
  8. 三、软考·系统架构师——计算机网络基础
  9. 学习英文-学以致用【场景:吃饭与家务】
  10. 2020身高体重标准表儿童_儿童身高体重对照表下载-2020儿童身高体重标准表最新版高清版 - 极光下载站...