MISRA 2012学习笔记(2)-Rules 8.1-3

这篇具有很好参考价值的文章主要介绍了MISRA 2012学习笔记(2)-Rules 8.1-3。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Rules

8.1标准的C环境

Rule 1.1 程序不得违反标准 C 语法和约束,并且不得超出具体实现的编译限制

等级:必要

分析:可判定,单一编译单元

适用:C90,C99

展开:程序只能使用选定的标准版本(参见第3.1节)中指定的C语言及其库的那些特性。

该标准允许实现提供语言扩展,并且该规则允许使用这种扩展。

除非使用语言扩展,否则程序不得有以下行为:

•包含任何违反标准中描述的语言语法的内容;

•包含任何违反标准所施加的约束

程序不得超过实施方规定的编译限制。最低编译限制由标准规定,但实现可能提供更高的限制。

注意:符合标准的实现会生成语法和约束违规的诊断,但要注意:

•诊断不一定是错误,也可以是一个警告;

•程序可以被编译并生成可执行文件,尽管存在语法或约束违反;

注意:当超过编译限制时,符合标准的实现不需要生成诊断;可以生成可执行文件,但不能保证正确执行。

原理:与ISO/IEC 9899支持版本之外的语言特性相关的问题在本指南的开发过程中未被考虑。

有一些轶事证据表明,一些不符合标准的实现未能诊断约束违反,例如在[38]p135中,题为“写入常量区域的错误”的示例2。

示例:一些C90编译器使用__inline关键字提供对内联函数的支持。使用__inline的C90程序将遵守此规则,前提是它打算使用这样的编译器进行编译。

许多用于嵌入式目标的编译器提供了附加的关键字,例如,这些关键字用对象所在的内存区域的属性来限定对象类

•__zpage:对象可以使用短指令访问

•__near:指向对象的指针可以保留16位

•__far:指向对象的指针可以保留24位

使用这些附加关键字的程序将遵循此规则,前提是编译器支持将这些关键字作为语言扩展。

Rule 1.2 不应该使用语言扩展

等级:建议

分析:不可判定,单一编译单元

适用:C90,C99

原理:依赖于语言扩展的程序可能比不依赖于语言扩展的程序更不容易移植。虽然标准要求一个符合标准的实现文档记录它提供给该语言的任何扩展。但还是存在这样的风险,即该文档可能无法在所有情况下提供对行为的完整描述。

如果不应用此规则,则应该在项目的设计文档中证明使用每种语言扩展的决定是合理的。还应该记录确保有效使用每个扩展的方法,例如检查编译器及其诊断

人们认识到在嵌入式系统中使用语言扩展是必要的。标准要求扩展不能改变任何严格符合标准的程序的行为。例如,编译器可以作为扩展实现对二进制逻辑运算符的完整求值,尽管标准规定一旦可以确定结果就立即停止求值。这样的扩展不符合标准,因为逻辑与操作符的右操作数总是会出现副作用,从而导致不同的行为(可能出现异常)。

Rule 1.3 不得发生未定义或严重的未指定行为

等级:必要

分析:不可判定,系统范围

适用:C90,C99

展开:一些未定义的需要和未指定的行为由特定的规则处理。此规则防止所有其他未定义的需要和关键的未指定行为。附录H列出了未定义的必需行为和那些被认为是关键的未指定行为。

原理:任何产生未定义或未指定行为的程序都可能不会以预期的方式运行。在许多情况下,其结果是使程序不可移植,但也有可能发生更严重的问题。例如,未定义的行为可能会影响计算的结果。

如果软件的正确操作依赖于此计算,则系统安全可能受到损害。如果未定义的行为只在极少数情况下出现,那么问题就特别难以发现。

许多MISRA C指南的设计都是为了避免某些未定义和未指定的行为。例如,遵守所有规则11.4、规则11.8和规则19.2确保在C中不可能创建指向用const限定类型声明的对象的非const限定指针。

这避免了C90 [undefini ned 39]和C99 [undefini ned 61]。然而,其他行为没有被特定的指导方针所涵盖,例如,因为

•不太可能会遇到这种行为;

•除了应该避免这种行为的明显声明之外,没有任何实际的指导可以给出

MISRA C没有为每个未定义的需要和关键的未指定行为引入指导方针

指导方针直接针对那些被认为最重要和最有可能在实践中发生的问题。那些没有具体指导方针的行为都包含在这一条规则中。附录H列出了所有未定义的和关键的未指定行为,以及防止其发生的MISRA C指南。因此,它指示了哪些行为应该被这条规则所阻止,哪些行为被其他规则所覆盖。

注意:一些实现可能为标准中列出的一些未定义和未指定的行为提供定义良好的必需行为。如果依赖于这些定义良好的行为,包括通过语言扩展,则有必要在这些行为方面偏离此规则。

8.2未使用的代码(Unused code)

Rule2.1 项目不应包含无法访问的代码

等级:必要

分析:不可判定,系统范围

适用:C90,C99

原理:如果程序没有表现出任何未定义的行为,那么不可达代码就不能执行,也不会对程序的输出产生任何影响。因此,出现不可达代码可能表明程序逻辑中存在错误。

一般编译器会在编译时移除所有不可达代码,尽管它并非必须这么做。而那些无法被编译器移除的不可达代码将造成资源浪费,比如:

•它占用目标机器的内存空间;

•它的存在可能会导致编译器选择更长,更慢的跳转指令时,转移控制周围的不可达代码;

•在一个循环中,它可以防止整个循环驻留在指令缓存中

为了处理异常情况,有时需要插入看起来不可访问的代码。例如,在switch语句中,控制表达式的每个可能值都由显式的case覆盖,则应根据规则16.4提供默认子句。default子句的目的是捕获一个通常不应该出现,但可能由于以下情况而产生的值:

•程序中存在未定义的行为;

•处理器硬件故障

如果编译器能够确认 default 子句不可达,则可以将其删除,从而清除该防御措施。如果该防御措施非常重要,则下述两者必须满足其一:要么保证编译器在证实不可达时仍保留该代码,要么采取措施使防御代码可达。前者与本规则有偏差,可能需要检查目标代码或使用单元测试来保证这种偏差。后者通常可以通过易失性(volatile)访问来实现。举例来说,编译器一般在执行 switch 语句前,已经确定了其条件 x 的值是否被 case 子句所覆盖,如:

uint16_t x;
switch (x)
/* 通过强制通过volatile限定左值访问x,编译器必须假定控制表达式可以取任何值: */
switch ( *( volatile uint16_t * ) &x )

注意:被预处理器指令有条件地排除的代码不受此规则的约束,因为它不会出现在编译的后期阶段

示例:

en um light { red, amber, red_amber, green };
enum light next_light ( enum light c )
{
 enum light res;
 switch ( c )
 {
 case red:
 res = red_amber;
 break;
 case red_amber:
 res = green;
 break;
 case green:
 res = amber;
 break;
 case amber:
 res = red;
 break;
 default:
 {
 /*
 * This default will only be reachable if the parameter c
 * holds a value that is not a member of enum light.
 */
 error_handler ( );
 break;
 }
 }
 return res;
 res = c; /* Non-compliant - this statement is
 * certainly unreachable */
}

最后一行不可能执行,所以违反了本规则。

Rule2.2 不得有无效代码(dead code)

等级:必要

分析:不可判定,系统范围

适用:C90,C99

展开:不论保留其执行还是被删除,均不会影响影响程序行为的操作,即构成无效代码。此处,我们假定语言扩展所引用的操作始终会对程序行为产生影响。

注意:嵌入式系统的行为通常不仅取决于其行为的性质,还取决于它们发生的时间

注意:不可达代码不是无效代码,因为它们不会被执行。不可达代码与无效代码的差别:不可达代码不会被执行,无效代码会被执行

原理:无效代码的存在,可能表明程序逻辑中存在错误。由于无效代码可能会被编译器删除,因此它可能会引起混乱。

例外:强制转换为 void 是显示声明有意不使用的值。因此,强制转换本身不是无效代码。它被视为使用了操作数的值,所以它不被定性为无效代码。

示例:在此示例中,假定p 指向的对象在其他函数中使用。

extern volatile uint16_t v;
extern char *p; 
void f ( void )
{
uint16_t x;
( void ) v;
( int32_t ) v; 
v >> 3;
x = 3;
*p++;
( *p )++;
/* 合规 - v 虽有副作用, 但其可被访问, 且强转 void 是被例外
* 允许的 */
/* 违规 - 执行无效 */
/* 违规 - ">>"运算无效 */
/* 违规 - "="运算无效, x 随后未被读取 */
/* 违规 - "*"运算的结果未被使用 */
/* 合规 - *p 自增 */
}

在下面的合规的示例中, _asm 关键字是语言扩展,而不是函数调用操作,因此不是无效代码。

 _asm ( "NOP" );

在下面的示例中,函数 g 不包含无效代码,且其本身也不是无效代码,因为它不含任何操作。但是对它的调用无效,因为删除它不影响程序行为。

void g(void)
{
/* 合规 - 此函数中无任何操作 */
}
void h(void)
{
g(); /* 违规 - 该调用可以被移除 */
}

Rule 2.3 项目不应包含未被使用的类型(type)声明

等级:建议

分析:可判定,系统范围

适用:C90,C99

原理:如果一个类型被声明但从未被使用过,对于审阅者来说,无法确定该声明是多余的还是被错误闲置的。
示例:

int16_t unusedtype(void)
{
typedef int16_t local_Type; /* 违规 */ 
return 67;
}
Rule2.4项目不应该包含未使用的tag声明

等级:建议

分析:可判定,系统范围

适用:C90,C99

原理:如果一个类型标签被声明但从未被使用过,对于审阅者来说,无法确定该类型标签是多余的还是被错误闲置的。
示例:在下面的示例中,标记状态未被使用,并且可以在不使用它的情况下编写声明

void unusedtag ( void )
{
 enum state { S_init, S_run, S_sleep }; /* Non-compliant */
}

在下面的示例中,标记record_t仅在record_1_t的typedef中使用,当需要该类型时,在翻译单元的其余部分中使用。通过省略record2_t定义中的标记,可以以兼容的方式编写该类型定义。

typedef struct record_t /* Non-compliant */
{
 uint16_t key;
 uint16_t val;
} record1_t;
typedef struct /* Compliant */
{
 uint16_t key;
 uint16_t val;
} record2_t;

在使用自定义结构体时,使用typedef时需要省略struct后的标签

Rule 2.5 项目不应包含未被使用的宏(macro)声明

等级:建议

分析:可判定,系统范围

适用:C90,C99

原理:如果一个宏被声明但从未被使用过,对于审阅者来说,无法确定该宏是多余的还是被错误闲置的。

void use_macro(void)
{
#define SIZE 4
#define DATA 3 /* 违规 - DATA 未被使用 */ 
use_int16(SIZE);
}

所有未使用的宏定义都应该删除

Rule 2.6 函数不应包含未被使用的执行标签(label)声明

等级:建议

分析:可判定,单一编译单元

适用:C90,C99

原理:如果一个执行标签(label)被声明但从未被使用过,对于审阅者来说,无法确定该执行标签是多余的还是被错误闲置的。
示例:

void unused_label(void)
{
int16_t x = 6;
label1: /* 违规 */ 
use_int16(x);
}

label一般在汽车c软件中用的比较少。

tag 和 label,两者翻译为中文都是标签,差别在于 tag 为枚举、结构体、联合体类型的标签,label
为 goto 语句执行目的地的标签,本文中为区分,将它们分别描述为了类型标签与执行标签。

Rule 2.7 函数中不应有未使用的变量

等级:建议

分析:可判定,单一编译单元

适用:C90,C99

原理:绝大多数函数都将使用它们所定义的每一个参数。如果函数中的参数未被使用,则可能函数的实现与其预期定义不匹配。本规则强化描述了这一潜在的不匹配

void withunusedpara(uint1 6_t *para1, int16_t unusedpara) /* 违规 - 参数未使用 */
{
*para1 = 42U;
}

函数中定义未使用的变量都应该删除。

8.3 注释(Comments)

Rule 3.1 字符序列“/*”和“//”不得在注释中使用

等级:必要

分析:可判定,单一编译单元

适用:C90,C99

原理:“/*”和“//”均为注释起始的字符序列,如果在一段由“/*”起始的注释中,又出现了“/*”或“//”,那么很可能是由缺少“*/”引起的。

如果这两个注释起始的字符序列出现在由“//”起始的注释中,则很可能是因为使用“//”注释掉了代码。

如果这两个注释起始的字符序列出现在由“//”起始的注释中,则很可能是因为使用“//”注释掉了代码。

例外:“//”起始的注释里,允许再次出现“//”。
示例 :

/* some comment, end comment marker accidentally omitted
<<New Page>> 
Perform_Critical_Safety_Function(X);
/* this comment is non-compliant */

第一段注释中没有*/结尾,导致Perform_Critical_Safety_Function函数也被注释了。

所以注释时,/*后面必须跟*/,而不能跟/*或//,可能会导致意外的注释。

在下面 C99 代码的示例中,“//”的出现改变了程序的含义:

x = y // /*
 + z
 // */
 ;

得到x = y + z;但应该是x = y;如果没有两个//注释开始序列。

//后面也不能跟/*,但可以跟//

Rule 3.2 “//”注释中不得使用换行(即“//”注释中不得使用行拼接符“\”)

等级:必要

分析:可判定,单一编译单元

适用:C90,C99

展开:当“\”字符后紧跟换行符时,将发生行拼接。

原理:如果包含//注释的源行以源字符集中的\字符结尾,则下一行将成为注释的一部分。这可能会导致无意中删除代码

注意:行拼接在C90和C99的第5.1.1.2(2)节中都有描述
示例:在下面的违规示例中,包含 if 关键字的物理行在逻辑上是前一行的一部分,因此是注释

extern bool_t b; 
void f(void)
{
uint16_t x = 0; // comment \
if (b)
{
++x; /* if 语句被作为注释处理, 这里无条件执行 */
}
}

使用//注释时,不允许加行拼接符\,可能会意外屏蔽代码文章来源地址https://www.toymoban.com/news/detail-647607.html

到了这里,关于MISRA 2012学习笔记(2)-Rules 8.1-3的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【小猫爪】AUTOSAR学习笔记08-Communication Stack之Com模块

      这一节来学习一下Communication Stack中一个关键模块,那就是Com模块。    首先的了解一下AUTOSAT面向信号的通信理念,什么个意思呢?这里的信号可以理解成是应用层关心的实际值,比方说电压值,电流值,转速等,这些都是信号,应用层接收和发送信号的时候,它只需要

    2024年02月16日
    浏览(40)
  • 【小猫爪】AUTOSAR学习笔记12-功能安全之E2E模块

      从这一节开始,正式步入功能安全专题。这一节先来看一个与Communication Stack强相关的且与功能安全有关的模块,它就是E2E模块。   E2E在AUTOSAR架构中,它被定义成是一个函数库。E2E 可以保护安全相关的数据交换,避免数据交换过程中通信链路造成的错误。E2E通信保护库

    2023年04月25日
    浏览(37)
  • MAC MINI 2012安装Montery折腾笔记

    MAC MINI 2012安装Montery折腾笔记(作为电视盒子/远程开发机) 起因: 手头有个mac mini,2018年买的2手。一直都是10.12系统,处理python和苹果开发都受制于旧系统,很多软件也装不上,于是有了升级的需求,打算折腾下再战3年 直接升级 使用因特网恢复系统模式,恢复到最新适配

    2024年02月20日
    浏览(37)
  • AutoSar CanNm笔记

    网络管理的目的 是 使车辆网络中的 ECU 节点有序的睡眠和唤醒。 在没有通信需求的时候睡眠,在需要通信的时候唤醒, 可以节约汽车电池的电量。 CAN Network Management(CanNm) 是一种独立于硬件的协议实现的软件模块 , 只能在 CAN 网络上使用, 主要功能是协调网络正常运行和总

    2024年02月04日
    浏览(35)
  • 汽车电子笔记之:基于AUTOSAR的多核监控机制

    目录 1、概述 2、系统监控的目标 2.1、任务的状态机 2.2、任务服务函数 2.3、任务周期性事件 2.4、时间监控的指标 2.5、时间监控的原理 2.6、CPU负载率监控原理 2.6.1、设计思路 2.6.2、监控方法的评价 3、基于WDGM模块热舞时序监控方法 3.1、活跃监督 3.2、截至时间监督 3.3、逻辑监

    2024年02月10日
    浏览(40)
  • 汽车电子笔记之:AUTOSAR方法论及基础概念

    目录 1、AUTOSAR方法论 2、AUTOSAR的BSW 2.1、MCAL 2.2、ECU抽象层 2.3、服务层 2.4、复杂驱动 3、AUTOSAR的RTE 4、AUTOSAR的应用层 4.1、SWC  4.2、AUTOSAR的通信 4.3、AUTOSAR软件接口         AUTOSAR为 汽车电子软件系统开发过程 定义了一套通用的技术方法,即AUTOSAR方法论。该方法描述了从 系

    2024年02月11日
    浏览(47)
  • Autosar初学习

    前言: 已下面这张图为例,进行Autosar初学习中SWC设计。 简单解释一下这张图,S-R Interface中 Receive Port的话有两个 分别是输入SeatSwitch和PowerManagement; Sender Port有一个 DialLED, 有一个标定量Calibration 1、Simulink配置参数 新建模型,快捷键Ctrl+E,打开配置参数,改定步长、离散求解

    2024年04月12日
    浏览(19)
  • AUTOSAR - CANTP - 学习一 :理论基础

    目录 1、概述 2、名词缩写 2.1、前缀含义 2.2、协议数据缩写 3、帧类别

    2024年02月03日
    浏览(40)
  • 学习MS Dynamics AX 2012编程开发 3. 存储数据

    您应该始终尝试存储数据,并以尽可能好的方式将其与其他数据关联起来,因为这将减少在编码上花费的时间。它还将确保您正在构建的解决方案更加稳定,性能更好。 本章将向您展示如何创建可以存储数据的表,如何创建表之间的关系,以及如何通过创建唯一索引和删除操

    2024年02月04日
    浏览(48)
  • 《The Element of Style》阅读笔记 —— 章节 I Elementary Rules of Usage

    前言 :本科期间担任科研助理时,有幸从导师那里借来这本书通读,只记得自己当时在本子上做了一些笔记,但是想不起来具体记了什么😂前段时间再次从学院的讲座活动中听闻这本书,决定重温一遍,本篇为此书第一章的阅读笔记。 本书电子版链接:http://www.jlakes.org/ch

    2024年02月05日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包