在出现有关GCC 10中静态分析的翻译文章,以及在这里的商用静态分析仪PVS-Studio的开发人员的代表的预期反应之后,我问:“为什么代表们拒绝使用如此简单的静态分析示例来测试其产品,他们是否隐藏了?这些是什么? ”安德烈2008是的,这对我来说并不有趣。捕获/未捕获到综合错误,这并未说明分析仪的功能
他们应该以某种方式对产品进行单元测试吗?如果不使用这样简单的综合示例,该如何进行?实际上,我必须自己做。测试编号1。双精度错误的最简单示例
诊断与:V586为释放相同的内存空间,两次调用了“ free”功能。检查第一个参数。检查行:5、6。1_dbl_free.c 6通过测试编号2。longjmp()由免费()
malloc中的常量发誓难以理解,但检测到错误-无法访问的代码和未使用的内存:V118 malloc()函数以参数的形式接受危险的表达式。2_longjump.c 13V779检测到无法访问的代码。可能存在错误。2_longjump.c 15V799在为其分配了内存之后,不再使用'ptr'变量。考虑检查此变量的使用。2_longjump.c 13通过测试编号3。Malloc()泄漏和fopen()未关闭文件
发现:V118 malloc()函数以参数的形式接受危险的表达式。3_fopen.c 7V773退出了“ f”文件句柄的可见性范围,而没有关闭文件。资源泄漏是可能的。3_fopen.c 9V773退出了“ p”指针的可见性范围,而没有释放内存。可能发生内存泄漏。3_fopen.c 9V799在为其分配了内存之后,不再使用'p'变量。考虑检查此变量的使用。3_fopen.c 7通过测试编号4。释放后监视内存使用情况
检测到错误:V774释放内存后使用了'n'指针。4_use_after_free.c 9V591非void函数应返回一个值。4_use_after_free.c 11通过测试编号5。非堆指针释放控制(堆)
发出了非错误警告:V104在算术表达式中将'n'隐式转换为memsize类型:sizeof(int)* n 5_free_nonheap.c 11V799在为其分配了内存之后,不再使用'ptr'变量。考虑检查此变量的使用。5_free_nonheap.c 11失败测试编号6。无效的signal()处理程序内部调用
失败,尽管这是一种非常具体的诊断,所以我不会对此进行指责。接下来,我浏览了GCC 10中的诊断程序列表并添加了示例,以便使用源代码进行进一步测试。测试编号7。双重关闭文件并释放关闭的文件*
PVS未检测到这些错误,GCC 10检测到两次闭合,但对于闭合手柄未检测到自由。#include <stdlib.h>
void closefile(FILE* f) {
fclose(f);
}
void test(const char *filename) {
FILE *f = fopen(filename, "r");
void *p = malloc(1024);
closefile(f);
fclose(f);
free (p);
free(f);
}
失败的测试编号8。longjmp()已过时的堆栈
PVS没有发现任何问题,GCC10正常工作#include <setjmp.h>
#include <stdlib.h>
static jmp_buf env;
static int i;
static void inner(void) {
longjmp(env, 1);
}
static void middle(void) {
inner();
}
void outer(void) {
i = setjmp(env);
}
void outer_x2(void) {
outer();
if (i == 0)
middle();
}
失败的测试编号9。返回指向堆栈变量的指针
尽管在简单的情况下,GCC都会检测到这两个参与者都失败了,但它不是-fanalyzer函数(或者可能尚未实现)。#include<stdlib.h>
struct str1 {
char buf[10];
};
struct str1 * ret(int sel)
{
struct str1 var1, *pval;
if(sel == 1)
pval = &var1;
else if(sel != 1)
pval = (struct str1 *)malloc(1000);
return pval;
}
失败的测试编号10。污染数组索引和未初始化值的使用诊断
看来他们还没有在GCC10- fanalyzer中工作。正如许多次证明的那样,PVS抓住了这一点。已通过结论
PVS-Studio中肯定有静态分析。尽管并非没有缺点,但值得使用它,特别是因为不仅可以从静态分析领域中检测到许多人为错误,还可以检测到它。