main content

在执行期间无法到达的代码 -凯发k8网页登录

在执行期间无法到达的代码

描述

不可达代码使用语句覆盖率来确定在执行期间是否可以到达代码的某个部分。语句覆盖率检查是否执行了某个程序语句。如果某个语句具有测试条件,并且至少发生了其中一个测试条件,则该语句将被执行并且可达。没有发生的测试条件不会被认为是死代码,除非它们有相应的代码分支。如果所有测试条件都没有发生,则该语句不会执行,并且每个测试条件都是一个不可达代码实例。例如,在以下代码的 switch 语句中,case 3 永远不会发生:

void test1 (int a) {
	int tmp = 0;
	if ((a!=3)) {
		switch (a){
			case 1:
				tmp  ;
				break;
			default:
				tmp = 1;
				break;
/* case 3 falls through to 
   case 2, no dead code */
			case 3:
			case 2:
				tmp = 100;
				break;
		}
	}
}
void test2 (int a) {
	int tmp = 0;
	if ((a!=3)) {
		switch (a){
			case 1:
				tmp  ;
				break;
			default:
				tmp = 1;
				break;
// dead code on case 3
			case 3:
				break;
			case 2:
				tmp = 100;
				break;
		}
	}
}

test1() 中,case 3 将穿透执行到 case 2,并且检查结果显示没有死代码。在 test2() 中,检查结果显示 case 3 存在死代码,因为下一行中的 break 语句未执行。

不可达代码的其他示例包括:

  • 如果测试条件的计算结果始终为 false,则对应的代码分支不可到达。在窗格中,该分支的左大括号显示为灰色。

  • 如果测试条件的计算结果始终为 true,则该条件是冗余的。在窗格中,条件关键字(例如 if)显示为灰色。

  • 跟在 breakreturn 语句后的代码。

如果某个代码块的左大括号在窗格中显示为灰色,要突出显示整个块,请双击该大括号。

检查操作的对象是函数内的代码。未调用函数不可达函数检查将确定是否函数本身未被调用,或者是从不可达代码内调用的。

对此检查进行诊断

示例

#define true 1
#define false 0
 
typedef enum {
  intermediate, end, wait, init
} enumstate;
 
enumstate input();
enumstate inputref();
void operation(enumstate, int);
  
int checkinit (enumstate stateval)  {
  if (stateval == init) 
    return true;
  return false;
}
 
int checkwait (enumstate stateval)  {
  if (stateval == wait) 
    return true;
  return false;
}
  
void main()  {
  enumstate mystate = input(),refstate = inputref() ;
  if(checkinit(mystate)){
    if(checkwait(mystate)) {
      operation(mystate,checkinit(refstate));	
    } else {
      operation(mystate,checkwait(refstate));
    }
  }
} 

在此示例中,只有当 mystate = init 时,main 才会进入 if(checkinit(mystate)) 分支。因此,在该分支内,polyspace® 会认为 mystate 具有值 initcheckwait(mystate) 始终返回 false 并且 if(checkwait(mystate)) 的第一个分支是不可达的。

更正 - 删除冗余测试

一种可能的更正方法是删除冗余测试 if(checkwait(mystate))

#define true 1
#define false 0
 
typedef enum {
  intermediate, end, wait, init
} enumstate;
 
enumstate input();
enumstate inputref();
void operation(enumstate, int);
int checkinit (enumstate stateval)  {
  if (stateval == init) 
    return true;
  return false;
}
 
int checkwait (enumstate stateval)  {
  if (stateval == wait) return true;
  return false;
}
   
void main()  {
  enumstate mystate = input(),refstate = inputref() ;
  if(checkinit(mystate))
    operation(mystate,checkwait(refstate));
} 
#include 
#include 
int roll() {
  return(rand()%6 1);
}
void operation(int);
     
void main()   {
    srand(time(null));
    int die = roll();
    if(die >= 1 && die <= 6)
      /*unreachable code*/
      operation(die);
  }

在此示例中,roll() 返回一个介于 1 到 6 之间的值。因此,main 中的 if 测试的计算结果始终为 true,是冗余的。如果有一个对应的 else 分支,则 else 语句上会显示灰色错误。如果没有 else 分支,则 if 关键字上会显示灰色错误来指示冗余情况。

更正 - 删除冗余测试

一种可能的更正方法是删除 if(die >= 1 && die <=6) 条件。

#include 
#include 
int roll() {
  return(rand()%6 1);
}
void operation(int);
     
void main()   {
  srand(time(null));
  int die = roll();
  operation(die);
}
#include 
#include 
#define true 1
#define false 0
int roll1() {
  return(rand()%6 1);
}
int roll2();
void operation(int,int);
    
void main()   {
  srand(time(null));
  int die1 = roll1(),die2=roll2();
  if((die1>=1 && die1<=6) || 
     (die2>=1 && die2 <=6))
  /*unreachable code*/
    operation(die1,die2);
}

在此示例中,roll1() 返回一个介于 1 到 6 之间的值。因此,if 测试的第一部分 if((die1>=1) && (die1<=6)) 始终为 true。因为 if 测试的两个部分通过 || 组合在一起,所以不管第二部分如何,if 测试始终为 true。因此,if 测试的第二部分不可达。

更正 - 使用 && 来组合测试

一种可能的更正方法是使用 && 来组合 if 测试的两个部分,而非使用 ||

#include 
#include 
#define true 1
#define false 0
int roll1() {
  return(rand()%6 1);
}
int roll2();
void operation(int,int);
    
void main()   {
  srand(time(null));
  int die1 = roll1(),die2=roll2();
  if((die1>=1 && die1<=6) && 
     (die2>=1 && die2<=6))
    operation(die1,die2);	
}
typedef enum {init, run, completion} states;
int getaninput();
states a = init;
void f(int b)
{
    switch (a) {
    case init: {
        if (b == 3) {
            a = completion;
        }
        break;
    }
    case completion: {
        if (b == 1) {      //unreachable code
            //....
        }
        break;
    }
        //...
    }
}
void main()
{
    int b = getaninput();
    f(b);
    f(b);
}

有时候,某个代码块可能因为变量值受代码中前面的运算约束而不可达。如果您不理解为什么某个条件始终为 true 或 false,请查看条件中的变量是否因为前面的某个运算而受到约束。

在此示例中,函数 getaninput() 已上桩,因为未提供它的定义。通过 getaninput() 初始化的变量 b 可以接受 int 数据类型允许的任何值。在 f() 调用中,b 看起来可以具有包括值 1 和 3 在内的任何值。不过,条件 (b == 1) 似乎为 false,对应的代码块不可达。

请观察两个 f() 调用。在第一个 f() 调用中,switch 语句选择 case init。在 case init 中,b 可以是完整范围。如果 b 等于 3,则 a 被设置为 completion。第二次调用 f() 函数时,switch 语句可以选择 case initcase completion。因为可以选择 case completion 的唯一途径是当 b 先前等于 3 时,并且因为在 case init 外部没有对 b 进行操作,因此 polyspace 假定 b 仍然等于 3。因此,if 语句条件 (b == 1) 永远不会得到满足,这导致 case completion 中出现不可达代码。

检查信息

组:数据流
语言:c | c
首字母缩写: unr
网站地图