MC9S12G128模块化分层化软件架构之八_QAC静态代码分析

内容

修改历史

内容

1        overview

1.1        目的

2        QAC基础知识

2.1        introduction

2.2        message等级

2.2.1        Level 0: information

2.2.2        Level 1: Obsolete Messages

2.2.3        Level2: Minor

2.2.4        Level 3: Major

2.2.5        Level 4: Local Standards

2.2.6        Level 5: Dataflow Analysis

2.2.7        Level 6: portability

2.2.8        Level7: Undefined behavior

3        meesage help

4        QAC 报issue的点

4.1        LEVEL6: [C99] Trailing comma at the end ofan enumerator-list.

4.1.1        修改的代码

4.2        level 7: The identifier is reservedfor use by the library.

4.2.1        例子

4.2.2        修改的代码

4.3        level3: An expression of ‘essentially signed’ type is being used as the operand ofthis bitwise operator.

4.3.1        例子

4.3.2        对应代码中的message

4.3.3        修改的代码

4.4        level3: An expression of ‘essentiallyBoolean’ type is being converted to unsigned type on assignment.

4.4.1        修改的代码

4.5        level2: Loop control variable in this ‘for’ statement is modified in the body of theloop.

4.5.1        例子

4.5.2        对应的代码中的message

4.5.3        修改的代码

4.6        level2: This statement has no side-effect – it can be removed.

4.6.1        例子

4.6.2        对应的代码中的message

4.6.3        修改的代码

4.7        level2: function with internal linkage, is being defined without a previousdeclaration.

4.7.1        对应的代码中的message

4.7.2        修改的代码

4.8        level 2: A function counld probablybe used instead of this function-like macro.

4.8.1        例子

4.9        level 8: initializer pointer to amore heavily qualified type.

4.9.1        例子

4.9.2        对应的代码中的message

4.9.3        修改的代码

4.10     level 3: A non-constant expression of‘essentially signed’ type is being converted to unsigned type on assignment.

4.10.1      对应的代码中的message

4.10.2      修改的代码

4.11     level 2:Array declared with unknown size.

4.11.1      例子

4.11.2      修改的代码

4.12     Macro parameter not enclosed in ().

4.12.1      更改的代码

5        MISRA C 2004

5.1        MISARC introduction

5.2        Rule10.1 The value of an expression of integer type shall not be implicitlyconverted to a different underlying type if: a) it is not a conversion to awider integer type of the same signedness, or b) the expression is complex, orc) the expression is not constant and is a function argument, or d) theexpression is not constant and is a return expression.

5.2.1        例子

5.2.2        根据该条rule修改的代码

5.3        Rule20.2  The names of standard librarymacros, objects and functions shall not be reused. & Rule 1.2:No reliance shall be placed on undefined or unspecified behaviour.

5.3.1        根据该条rule修改的代码

5.4        Rule When an array is declared withexternal linkage, its size shall be stated explicitly or defined implicitly byinitialisation.

5.4.1        例子

5.4.2        根据该条rule修改的代码

5.5        All if … else constructs shall beterminated with an else clause.

5.5.1        例子

5.5.2        根据该条rule修改的代码

5.6        rule 12.7Bitwise operators shall not be applied to operands whose underlying typeis signed.

5.6.1        例子

5.6.2        根据该条rule修改的代码

5.7        Rule14.2 All non-null statements shall either have at least one side effect howeverexecuted, or cause control flow to change.

5.7.1        根据该条rule修改的代码

5.8        Rule 8.1 functions shall haveprototype declaration and the prototype shall be visible at both the functiondefinition and call.

5.9        Rule19.7 A function should be used in preference to a function-like macro.

5.9.1        例子

5.10     Rule 19.4: C macros shall only expandto a braced initialiser, a constant, a string literal, aparenthesisedexpression, a strorage class specifier, or a do-while-zero construct.

5.10.1      例子

5.11     Rule13.6: Numeric variables being used within a for loop for iteration countingshall not be modified in the body of the loop.

5.11.1      例子

5.12     Rule 19.10 in the definition of afunction-like macro each instance of a parameter shall be enclosed inparentheses unless it is used as the operand of # or ##.

5.13     Rule 8.12: When an array is declared with externallinkage, its size shall bestated explicitly or defined implicitly by initialisation.

6        MISAR C 2012

 

根据QAC检测报告修改的最新代码下载链接:

https://download.csdn.net/download/Sure_gengjia/12987470

修改后的代码的QAC报告下载链接:

https://download.csdn.net/download/Sure_gengjia/12987399

未修改的代码的QAC报告下载链接:

https://download.csdn.net/download/Sure_gengjia/12987383

 

关注激活未来公众号,后台回复“MISAR C 2012”即可免费获取“MISRA C_2012 Guidelines for the use of the C language in critical systems.pdf

”文档下载链接,回复“QAC”即可免费获取QAC-8.1-Win-UsersGuide.pdf使用手册下载链接。

 

1      overview

1.1    目的

本文档用于起点开发板的软件优化说明。

不局限于硬件功能的实现,着眼于实现高质量、优美的软件。                           

2      QAC基础知识

2.1    introduction

QA·C是用于C代码的深度静态分析器。 QA·C旨在帮助提高软件开发的质量。

QA·C在逐个文件和完整项目的基础上分析源代码,以识别C语言的危险用法。包含1300多个警告消息的库用于突出显示那些不可移植的、难以维护的、过于复杂或可能引起问题的方式编写的源码。

该工具还可以识别不符合ISO C90标准(ISO / IEC 9899:1990)或依赖于未指定、未定义的行为的语言用法。该工具会在使用ISO C99标准的特定功能时发出警告,但确实支持其中许多功能的语义。

整个项目的源代码的警告消息通过浏览器显示,该浏览器对所有源文件中出现的消息进行分类和分组。

该工具的其他功能包括:

•提供可量化衡量代码属性的代码度量:基于函数的33个,基于文件的30个和项目级别的4个;

•功能结构图,可深入了解控制流程;

•关系图,用于演示函数调用,全局引用和文件树;

•关系统计分析,根据行业基准对代码质量进行全面评估;

•跨模块分析(CMA)功能,分析功能递归和各种全局标识符问题;

•一个基准模块,可简化对遗留代码的修改。

2.2    message等级

QAC中将message分为10个等级。

2.2.1         Level0:information

information等级的警告重要性最低。

annotations

注释

注释中的语法错误

CMA  信息

跨模块分析的产生的问题。

parsing recovery

分析恢复

从解析错误恢复的过程中生成的信息。

dataflow  recovery

从内部数据流分析故障中恢复的过程中生成的信息。

sub-message

额外的上下文子消息,用于澄清主要信息。

 

2.2.2         Level 1: Obsolete Messages

保留标记为过时的消息是为了向后兼容2个产品版本,并将随后将其删除。

2.2.3         Level 2: Minor

级别2信息识别那些可能会违反编码标准要求的问题,但这些问题不一定是严重的错误。级别2信息组与C语言的不同方面相关联。

2.2.4         Level 3: Major

Major信息是那些可能会识别出重大编码错误,异常或问题的信息。通常认为这些信息(如7、8和9级)太重要了,以至于没有充分的理由就无法忽略。 3级信息组与C语言的不同方面相关联。

2.2.5         Level 4: Local Standards

级别4信息识别那些不符合您的编程标准的功能。按照惯例,在安装QA·C模块时,会将其他信息组添加到级别4,其中将包含与编码标准中特定规则相对应的信息。

2.2.6         Level5: Dataflow Analysis

此级别的信息对运行时行为进行分析,确定问题,从严重的问题(如未定义的行为)到经常与编码和逻辑错误相关的条件。

conversion  to signed

转换成有符号

转化成不足够大以表示期望值的带符号类型。

conversion  to unsigned

转化成无符号

转化为无符号的值,被转化的值为负数或者是太大无法表示的值。

shift  operations

移位操作

结果不确定或者导致非零位丢失的移位操作。

overflow  and wraparound

溢出和环绕

导致有符号算术值溢出(未定义行为)或无符号算术环绕的操作

Array

数组

对数组或指针类型的对象进行的操作导致未定义的行为。

Pointer

指针

比较或减去指向不同对象的指针。

NULL  pointer

空指针

对NULL指针进行算术或取消引用操作。

Unset  data

未设定的数据

访问未设定数据的值。

Redundancy

冗余

冗余的初始化,表达式或赋值,通常与错误的逻辑关联

Invariant  operations

不变的操作

总是评估为true或false的表达式,经常与错误的逻辑相关联。

control  flow

控制流

无法访问的代码,无限循环,错误的返回语句。

overflow and wraparound:

当整数值增加到太大而无法存储在关联表示中时,就会发生整数溢出或环绕。发生这种情况时,该值可能会变成非常小的值或负数。当结果用于控制循环,做出安全性决定或确定行为的偏移量或大小(例如内存分配,复制,串联等)时,这对安全性至关重要。

2.2.7         Level 6: portability

ISO-C90  conformance limits

ISO-C90一致性限制

识别违反C90标准中定义的转换限制的信息。超出这些限制的代码可能无法移植到符合C90标准的实现中。

ISO-C99  conformance limits

ISO-C99  一致性限制

识别违反C99标准中定义的转换限制的消息。超出这些限制的代码可能无法移植到符合C99标准的实现中。

Implementation  defined

代码结构的行为方式可能会因不同的编译器而不同。

Language  extensions

QA·C能够解析不符合C90或C99标准的代码结构。

ISO  C99 language features

不属于C90语言定义的C99代码结构。

2.2.8         Level 7: Undefined behavior

CMA  undefined behavior

其行为在语言标准中很明显地是未定义的且已通过跨模块分析定义的构造。

explicitly  undefined

在语言标准中其行为被明显地描述为“未定义”的构造(不归类为依赖数据流)

implicitly  undefined

其行为未在语言标准中描述的构造,因此其行为未通过隐式定义(仅)。

3      meesage help

function-like  macro

用带括号的参数列表定义的宏,该列表由零个或多个参数组成。

  
  
  
  
  

4      QAC 报issue的点

4.1     LEVEL6: [C99]Trailing comma at the end of an enumerator-list.

枚举列表末尾的逗号。

ISO C99language features.

在枚举常量列表的末尾有逗号。ISO:C90无法识别此语法,但是ISO:C99允许使用此语法。

forexample:

 enum ED { ZERO=0, TWO=2, FOUR=4, };

对应的MISARC 2004 rule:1.1。

4.1.1         修改的代码

4.1.1.1          drio.h

等。

4.1.1.2          mdio_cfg.h

等。

4.2     level 7: The identifier is reserved for use by the library.

标识符保留给库使用。

使用保留名称去定义一个标识符不可取,因为该名称可能与系统库的现有版本或将来版本中的标识符冲突。以下标识符保留:

a)      以2个下划线开头;

b)      以1个下划线紧跟着一个大写字母开头;

c)       以1个下划线和一个其他的标识符开头;

4.2.1         例子

int __glob = 0;  /* 不符合 */

int _Glob = 1;   /* 不符合 */

对应的MISAR C 2004 rule:20.2。

4.2.2         修改的代码

4.2.2.1          apl_key.h

等。

4.3     level 3: An expression of ‘essentially signed’ type is being used asthe operand of this bitwise operator.

原始有符号类型的表达式用作位运算的操作数。

4.3.1         例子

void foo(int a)

{

a & 1u;           /* 不符合 */

a | 1u;            /* 不符合 */

~a;                 /* 不符合 */

a >> 1u;         /* 不符合 */

1u << a;         /* 不符合 */

}

对应的MISARrule 12.7。

 

4.3.2         对应代码中的message

4.3.2.1          drint.c

4.3.3         修改的代码

4.3.3.1          drint.c

4.4     level3: An expression of ‘essentially Boolean’ type is being converted tounsigned type on assignment.

分配时,“基本布尔”类型的表达式将转换为无符号类型。

相关的MISARCrule 10.1。

例子:

void foo (unsigned b);

 

unsigned test (int a)

{

unsigned uia = (a != 0);  /*不符合*/

foo(a < 0);                      /*不符合*/

uia = (a < 0);                 /*不符合*/

return (a == 0);              /*不符合*/

}

对应的MISAR C 2004rule 10.1。

4.4.1         修改的代码

4.4.1.1          bitop.h

BYTEOP_BIT_READ原宏定义:

#defineBYTEOP_BIT_READ_AT(data, bitidx)             (((uint8)(data) & BYTEOP_POWER_2(bitidx)) != 0U)

返回的值为bool型,true or false

改为:

#defineBYTEOP_BIT_READ_AT(data, bitidx)             ((((uint8)(data) & BYTEOP_POWER_2(bitidx)) != 0U) ? (uint8)1U :(uint8)0U)

返回的值为1U或0U

4.5     level 2: Loop control variable in this ‘for’ statement is modifiedin the body of the loop.

for语句的循环控制变量在循环体中被修改了。

在此“ for”循环中,被识别为控制变量的变量在循环体内进行了修改。

QAC通过检查 “ for-loop”中的3个表达式的来识别控制变量。通常,它是第二个表达式中的变量,并且是关系运算符的操作数。

在常规的for循环中,仅在for语句的第三个表达式中修改循环控制变量。循环中其他位置的修改可能会引起混乱。

4.5.1         例子

extern void foo(void)

{

int j;

for (j = 0; j < 10; j++)

{

   ++j;

}

}

对应的MISARC2004rule: 13.6。

4.5.2         对应的代码中的message

4.5.3         修改的代码

4.5.3.1          drint.c

4.6     level 2: This statement has no side-effect – it can be removed.

语句没有side-effect,可以移除。

可以被优化掉的代码。

sideeffects: 更改执行环境的动作。访问易失性对象,修改对象,修改文件或调用执行任何这些操作的函数都是副作用。

4.6.1         例子

void foo( int x )

{

int n = 0;

n == x;           /*报警告*/

}

对应的MISAR2004Rule 14.2。

4.6.2         对应的代码中的message

4.6.3         修改的代码

4.6.3.1          mdio.c

等。

4.7     level 2: function with internal linkage, is being defined without aprevious declaration.

一个被内部引用的函数在定义时没有提前的声明。

在文件中定义的所有的函数都应在文件顶部加原型声明,这很有帮助。这样可以避免在函数被声明之前被调用的可能性。在文件开始处的一个位置记录函数接口的方式也很有用。

例子:

static voidfoo(void)        /*没有提前声明*/

{

}

对应的MISAR 2004rule 8.1

4.7.1         对应的代码中的message

4.7.1.1          mdio.c

4.7.2         修改的代码

4.7.2.1          mdio.c

在文件头部增加static uint8 mdio_find_in_input_cfg(uint8port, uint8 pin)函数声明。

4.8     level 2:A function counld probably be used instead of this function-like macro.

类似函数的宏应当用函数替换。

该宏是表达式的形式,因此可以用一个函数代替。用函数替换类似函数的宏并不总是可行或方便。但是函数通常比宏更安全,因为可以对参数执行类型检查。

下面这些类似函数的宏会导致该条信息的产生:

·  有至少一个参数;

·  不包含’#’ or ‘##’操作符;

·  不包含’ {}; ‘或任何关键字;

对应的MISARC2004rule: 19.7。

4.8.1         例子

#define M1(a, b, c)    ( (a) + (b) + (c))        /* 不符合 */

#define M6(A, B)       ((A)[1] +(B)[2])         /* 不符合 */

对应的MISAR C2004 rule 19.7。

需要写成do-while(0)格式。

为什么写成do-while(0)格式,请看MISARC2004rule: 19.4 和 19.10。

4.9     level 8:initializer pointer to a more heavily qualified type.

初始化程序指向更严格的类型。

指针已使用表达式进行了初始化,该表达式指向更严格的类型。

ISO: C要求被初始化对象的类型必须具有初始化者指向的类型的所有的qualifier。因此,不允许使用类型为“ const TYPE *”(指向const TYPE的指针)或“ volatile TYPE *”(指向volatile TYPE的指针)的表达式来初始化类型“ TYPE *”(指向TYPE的指针)的对象;这样做将违反类型资格限制。

另一方面,使用类型“ TYPE *”的表达式初始化“ const TYPE *”或“ volatile TYPE *”甚至“ const volatile TYPE *”类型的对象是完全合法的。

原文:

A pointer has been initialized with anexpression which points to a more heavily qualified type.

ISO:Crequires that the type pointed to by the initialised object must have all thequalifiers of the type pointed to by the initializer. It is therefore notpermissible to initialize an object of type "TYPE *" (pointer toTYPE) with an expression of type "const TYPE *" (pointer to constTYPE) or "volatile TYPE *" (pointer to volatile TYPE); to do so wouldpermit type qualification restrictions to be violated.

On theother hand, it is perfectly legitimate to initialize an object of type"const TYPE *" or "volatile TYPE *" or even "constvolatile TYPE *" with an expression of type "TYPE *".

4.9.1         例子

extern int                        *gpi;

extern const int             *gpci;

extern volatile int          *gpvi;

extern const volatile int * gpcvi;

 

void test (void)

{

int                       *xpia    = gpi;            /* no message */

int                       *xpb     = gpci;          /* 不符合 */

int                       *xpc     = gpvi;          /* 不符合 */

int                       *xpd     = gpcvi;        /* 不符合 */

 

const int              *xpcia  = gpi;           /* no message */

const int              *xpcib  = gpci;         /* no message */

constint              *xpcic  = gpvi;         /* 不符合 */

constint              *xpcid  = gpcvi;      /* 不符合 */

 

volatile int           *xpvia  = gpi;           /* no message */

volatile int           *xpvib  = gpci;         /* 不符合 */

volatile int           *xpvic  = gpvi;         /* no message */

volatile int           *xpvod = gpcvi;      /* 不符合 */

 

const volatile int *xpcvia = gpi;          /* no message */

const volatile int *xpcvib = gpci;        /* no message */

const volatile int *xpcvic = gpvi;        /* no message */

const volatile int *xpcvid = gpcvi;      /* no message */

}

4.9.2         对应的代码中的message

4.9.2.1          drio_cfg.c

4.9.3         修改的代码

4.9.3.1          drio_cfg.h

typedef uint8 * DrRegType;

改为

typedef uint8 * DrRegType;

因为DDRE的定义和使用为:

4.10 level 3: A non-constantexpression of ‘essentially signed’ type is being converted to unsigned type onassignment.

“原始有符号的”类型的非常量的表达式转换为无符号类型。

void foo(unsigned b);

unsignedtest(short a)

{   

unsigned  uia = a;           /* 不符合 */

foo( a + 1 );                     /* 不符合 */

uia = (a – 1);                   /* 不符合 */

return a;                          /* 不符合 */

}

4.10.1       对应的代码中的message

4.10.2       修改的代码

4.10.2.1       drio.c

4.11 level2: Array declared with unknown size.

大小未知的数组声明。

数组声明时类型不完整。

仅当数组具有外部连接时才允许这样做。一些编码标准不赞成这种做法,因为它阻止工具检查数组下标操作的有效性。

4.11.1       例子

extern int xa[10];

extern int xb[];                       /* 警告 */

extern void foo(void)

{

xa[10] = 0;                        /* 警告,越界 */

xb[10] = 0;                        /* 没有警告,数组大小未知 */

}

对应的MISAR C2004 rule: 8.12。

4.11.2       修改的代码

4.11.2.1       drio_cfg.h

4.12 Macroparameter not enclosed in ().

宏参数未包含在()中。

在某些宏中,将参数括在替换列表的括号中这一操作很重要。并非所有的宏或所有参数都是如此。这取决于宏中如何使用参数。在某些类型的表达式中,将宏参数用作操作数时就会出现问题。考虑以下示例:

#define SQUARE(A)   (A * A)             /* 报警告 */

extern int foo(int n)

{

int r;

r = SQUARE(n);

r = SQUARE(n + 2);                       /* 报警告 */

return r;

}

对应MISARC2004rule19.10。

4.12.1       更改的代码

4.12.1.1       typedef.h

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值