C++ 我们还需要做静态分析吗?

C++ 我们还需要做静态分析吗?,c++,c,static-analysis,C++,C,Static Analysis,我的老板认为我们编写的任何代码(用C/C++)都必须符合静态分析工具(如MISRA/Lint)指定的标准。我对这一点的看法是,今天的编译器已经很成熟了,这真的是必需的吗 现在的问题是这种静态分析有多有效?简短回答:是的 长话短说:编译器确实在分析某些类型的“错误”方面越来越好,但它们工作的“深度”通常远远低于用于此的适当工具。特别是跨编译单元工作的工具,例如Coverity,它可以理解(例如)函数可能会以NULL的形式返回指针,如果返回,代码将崩溃,因为在访问指针之前没有检查NULL 静态分析工

我的老板认为我们编写的任何代码(用C/C++)都必须符合静态分析工具(如MISRA/Lint)指定的标准。我对这一点的看法是,今天的编译器已经很成熟了,这真的是必需的吗

现在的问题是这种静态分析有多有效?

简短回答:是的

长话短说:编译器确实在分析某些类型的“错误”方面越来越好,但它们工作的“深度”通常远远低于用于此的适当工具。特别是跨编译单元工作的工具,例如Coverity,它可以理解(例如)函数可能会以
NULL
的形式返回指针,如果返回,代码将崩溃,因为在访问指针之前没有检查
NULL

静态分析工具还可以检查锁的使用情况,而编译器通常不能这样做

至于“有多有效”,这实际上取决于您使用的工具、设置以及测试代码的效果。所以,“代码覆盖率”也在其中。在测试中,您是否检查了代码的每个分支?每一个可能导致行为差异的价值观?静态分析工具可以检测测试可能未涵盖的错误


(显然,这在您的特定业务中是否真正有意义是一个完全不同的讨论-这由您的老板和他/她的老板来决定)

好的静态分析工具分析循环复杂度,甚至“代码气味”之类的东西(参见Martin Fowler的重构书)。甚至文件或函数中的行数都是代码可以改进的线索。不过,我认为皮棉不能覆盖这些区域

此外,静态分析对于生成度量非常重要

这些指标可以显示:圈复杂度、类继承的深度和许多其他/依赖关系图/%的注释等(例如,有完整的功能列表)

还有一个优点是,大多数静态分析工具都允许您添加特定的规则,如果您的项目/公司有编码规则,这些规则可能会很有用


您还可以添加一个“持续集成”服务器,每天检查svn/git/其他开发分支,晚上进行分析。这样,第二天您就可以修复不符合规则集的代码。

这并不是说编译器不能像静态分析工具那样进行分析。问题在于,静态代码分析需要花费大量的时间,而且通常不需要每次编译。编译器通常是为平衡代码质量和编译时间而优化的。如果编译器碰巧在代码中发现错误,它会告诉您,但它没有时间主动查找错误。

是的,它会增加代码的可信度

MISRA规则广泛应用于实时系统中。许多软件审核员都要求遵守MISRA(通过运行MISRA支持的工具)

此外,MISRA(或类似标准)定义了一些繁琐的规则,以防止用户在某些编译器上做一些可能出错的花哨事情。例如,MISRA禁止使用指针算法,但没有编译器会对此发出警告

编辑: 另一个例子:下面的代码正在做许多人不期望的事情(由于浮点精度,x!=1.1)


编译器没有检测到这一点(在GCC4.6和Clang3.2上试用过)。但是几乎所有的静态分析工具都能检测到它。

是否仍然需要静态分析工具?绝对地编译器发出的警告越来越复杂,但仍然存在一个限制,即编译器通常一次只能处理一个源文件。每个文件都经过编译(*.c->*.o),最终生成的对象文件链接在一起。要进行真正有效的静态分析,您需要立即查看整个代码库,分析单个文件以及它们之间的交互。编译器通常不是这样设计的,因此仅编译器一个通常会忽略静态分析器拾取的内容。您不希望将此功能构建到普通编译器中,因为这会对性能造成相当大的影响。在我当前的项目上运行静态分析通常需要普通编译所需时间的4倍。您不希望在每个构建上都有额外的开销,因此最好将其分配到一个单独的专用工具,而不是在需要时运行(或者在某些现代编译器的情况下,默认情况下禁用一组单独的命令行选项)

静态分析有多有效?非常我的团队通过静态分析工具发现了大量的潜在问题,其中大部分问题几乎不可能通过其他方法找到。它特别擅长发现人类不擅长发现的复杂问题,比如那些涉及多个局部变量和全局变量之间相互作用的问题。即使您有很好的测试覆盖率,静态分析器也会发现各种单独通过测试很难找到的东西。这在嵌入式世界中更为真实,因为在嵌入式世界中,测试往往更加困难,自动化程度更低。根据我的经验,静态分析仪甚至向我们展示了一些我们根本不知道需要测试的问题

我绝对推荐对任何非平凡的软件项目使用静态分析工具。我实际上运行了两个独立的静态分析器(一个内置在编译器套件中,另一个是独立的实用程序);你可能会惊讶于一个会抓住另一个会错过的东西。我强烈建议您为您的分析运行制定一套定制的规则/测试,而不是简单地采用像MISRA这样的规则集。每个项目的需求都是不同的,许多行业范围的规范,比如MISRA,都包含了很多项目不需要的东西
int main(int agrc, char** argv){

    float x = 1.1;
    if(x == 1.1)
        printf("Yes!\n");
    else
        printf("OMG!\n");
    return 0;
}