主要内容

Polyspace Code Prover 结果中未被检查的代码的原因

问题

如果程序执行流的早期出现编译错误或红色检查,Polyspace® Code Prover™ 将不会分析程序的剩余部分。验证后,您会发现很大一部分代码未经过运行时错误检查。本主题列出了经 Code Prover 分析的代码占比偏低的各种可能原因。

例如,运行时检查仪表板上的下图显示,多达 60% 的函数未经过运行时错误检查。

可能的原因:编译错误

仅对不存在编译错误的文件进行完整分析。在包含编译错误的文件中,根据编译错误的性质,有些函数可能不会被分析:

  • 如果编译错误出现在函数体内部,则只有文件中不存在编译错误的剩余函数会被分析。

  • 如果编译错误出现在函数签名中或函数体外部,根据编译错误的性质,文件中的剩余函数可能会被分析,也可能不会被分析。

要检查是否有一些文件未编译,请查看分析日志。有关详细信息,请参阅View Compilation Errors When Running Polyspace Static Analysis

解决方案

修复编译错误并重新运行分析。

有关以下操作的详细信息:

可能的原因:早期红色或灰色检查

靠近函数调用层次结构的起始位置存在红色或灰色检查。红色或灰色检查会导致后续代码不被检查。

  • 红色检查:验证不会检查包含红色检查的代码块中的后续运算。

  • 灰色检查:灰色检查指示不可达代码。验证不会对不可达代码中的运算进行运行时错误检查。

如果您从未被检查的代码块中调用函数,验证也不会检查这些函数。如果靠近调用层次结构的起始位置存在红色或灰色检查,层次结构中更深层次的函数可能不会被检查。最终会导致大量代码未被检查。

例如,在以下代码中,4 个函数里只有 1 个被检查。函数 func_called_from_unreachable_1func_called_from_unreachable_2func_called_after_red 未被检查。只检查了 main

void func_called_from_unreachable_1(void) {
}

void func_called_from_unreachable_2(void) {     
}

void func_called_after_red(void) {
}

int glob_var;

void main(void) {
     int loc_var;
     double res;
     
     glob_var=0;
     glob_var++;
     
     if (glob_var!=1) {
           func_called_from_unreachable_1();
           func_called_from_unreachable_2();
     }
     
     res=0;
     /* Division by zero occurs in for loop */
     for(loc_var=-10;loc_var<10;loc_var++) {
	          res += 1/loc_var;
     }
     
     func_called_after_red();
}

解决方案

检查 main 函数或其他入口函数是否存在红色或灰色检查。检查您是否从后续未检查的代码中调用了大部分函数。

您也可以选取任意一个未检查的函数,调查其未被检查的原因。查看该原因是否适用于很多函数。要检测函数是否根本未从入口函数调用或者是从不可达代码中调用的,请使用选项检测未调用的函数 (-uncalled-function-checks)

审查红色或灰色检查并进行修复。

可能的原因:选项不正确

您未指定必要的分析选项。以下选项指定不正确时会导致代码不会被检查:

  • 配置多任务检查项:如果您正在验证多任务代码,则可以通过这些选项指定入口函数。

    可能的设定错误包括:

    • 您预期自动并发检测会检测线程创建,但您使用的线程创建原语尚不支持自动检测。

    • 在手动多任务设置中,您未指定所有入口函数。

  • 配置库验证:如果您的代码中不存在 main 函数,则可以通过这些选项生成该函数。验证模块或库时,您会用到这些选项。

    您未指定生成的 main 必须调用的所有函数。

  • 配置代码约束:通过这些选项,您可以对代码外部的变量范围指定约束或强制对函数进行插桩。

    可能的设定错误包括:

    • 您指定的变量范围过窄,导致原本可达的代码变得不可达。

    • 您无意中对一些函数进行了插桩。

  • 配置源代码和编译选项:通过这些选项,您可以模拟编译系统、指定编译器、定义或取消定义预处理器宏。

    您可能需要显式定义编译器隐式认为已定义的宏。

解决方案

按上面的顺序检查您的选项配置。如果设定不正确,请进行修复。

可能的原因:main 函数无法终止

此原因仅适用于多任务代码中整个入口函数未被检查的情况。

如果您手动配置多任务选项,则必须遵守 Polyspace 多任务模型的限制。尤其是,main 函数不能包含无限循环或运行时错误。否则,将不会检查入口函数。

例如,在此示例中,即使您将 task2 指定为入口函数,它也不会被检查。原因是 main 函数中存在无限循环。

void performTask1Cycle(void);
void performTask2Cycle(void);

void main() {
 while(1) {
    performTask1Cycle();
  } 
}

void task2() {
 while(1) {
    performTask2Cycle();
  }
}

您会看到 main 函数中的 while 关键字带有红色虚线下划线。工具提示指出该循环可能无法终止。

同样,如果发生运行时错误,导致运行时错误的函数调用会带有红色虚线下划线并附带工具提示。

解决方案:终止 main 函数

修复 main 函数无法终止的原因。

  • 如果原因是确定的运行时错误(红色检查),请修复该错误。

  • 如果原因是无限循环,请查明该循环必须是无限循环的原因。

    如果 main 函数中的无限循环代表周期任务,请终止 main 函数,并将无限循环移至另一个入口函数。您可以仅为了 Polyspace 分析的目的进行此更改,而不实际修改您的 main 函数。请参阅手动配置 Polyspace 多任务分析