检查和修复C/C++代码(以及其他语言)的有用工具

2020-05-11 03:20:57

PermalLink GitHub是5000多万开发人员的家园,他们一起工作,共同托管和审查代码、管理项目和构建软件。

报名。

可能你们中的许多人都遇到过错误,虽然它们很容易修复(例如,复制粘贴错误),但在修复它们之前,它们在代码中隐藏了几个月或几年。在许多情况下,这些问题的解决方案是静态和动态代码分析器和程序,以便通过函数检查内存泄漏或CPU时间使用情况,从而帮助更好地优化代码和搜索瓶颈。

我将要展示的所有工具对于开源项目都是免费的(PVS-Studio是一个小例外,但稍后会这样),其中许多工具可以很容易地与CI(在我的例子中是GitLab CI)集成,以进行自动代码和回归检查。

我已经与Sonarcloud、Cppcheck和Coverity Scan集成了很多项目,它们的代码和实现细节可以在这里找到--https://gitlab.com/dashboard/projects.。

Sonarcloud扫描的结果可以在这里找到-https://sonarcloud.io/organizations/qarmin-1/projects和cppcheck在GitLab上的给定项目中的管道中,例如https://qarmin.gitlab.io/-/godot/-/jobs/526221853/artifacts/report/index.html。

这可能是C/C++源文件中最基本、最容易使用的错误搜索程序,它不需要编译检查过的程序即可工作。

我们所要做的就是进入项目目录并在那里运行Cppcheck,或者使用图形版本并单击它。

它有很多种结果表示,但对我来说,最方便的方法是导出为html(如下面的示例所示)。

控制台-在项目文件夹内执行这些命令,报表文件夹内将生成一个包含代码和错误的HTML文件。

Sonarcloud允许您通过网站查看和分类潜在错误。它可以免费用于开源项目。它发现与Cppcheck类似的bug,而不是需要耗时的编译。

静态分析器在操作上类似于Sonarcloud(您也可以在线查看结果,对于开源解决方案是免费的),但它不允许将结果公开,因此每个人都必须请求访问它们。根据我的经验,它比以前的工具发现更多真正的错误。

-$Coverity_SCAN_TOKEN、$GITLAB_USER_EMAIL、$Coverity_SCAN_PROJECT_NAME等名称应使用您的令牌、名称等更改,g++rr.cpp-o rr.out应更改为正确的指令。

curl-o/tmp/cov-Analysis-linux64.tgz https://scan.coverity.com/download/linux64--表单项目=$COVERITY_SCAN_PROJECT_NAME--表单TOKEN=$COVERITY_SCAN_TOKENTAR xfz/tmp/cov-analysis-linux64.tgzcov-analysis-linux64-*/bin/cov-build--目录COV-INT g++rr.cpp-o r.outtar CFZ cov-int.tar.gz cov--INTURL https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME--表单TOKEN=$COVERITY_SCAN_TOKEN。--表单电子邮件=$GitLab_USER_EMAIL--表单文件[email protected]

PVS-Studio是一个商业静态代码分析器,用于检测打字错误、错误和安全漏洞。分析器可以离线检查源代码,即完全与互联网隔离。这对于有特殊安全和代码泄漏保护要求的项目非常有用。

PVS-Studio可在Windows、Linux、MacOS环境下运行。它支持与Azure DevOps、Travis CI、CircleCI、GitLab CI/CD、PlatformIO、Jenkins、SonarQube、Visual Studio等系统集成。已经为快速引入分析器开发了一个场景,甚至在一个大型的老项目中也是如此,例如,本文描述了这一场景。

您可以通过以下链接下载分析仪并申请为期一周的试用许可证:https://www.viva64.com/en/pvs-studio-download/。

虽然分析器定位为B2B解决方案,但许多开发人员可以在开源项目中甚至在封闭源代码项目中免费使用它。

开源项目。参与GitHub、GitLab或Bitbucket上的项目开发的开发人员可以免费使用PVS-Studio。免费许可不会扩展到镜像项目。可以获得为期1年的免费许可:

许可证到期后,您可以通过相同方式获取新的许可证密钥。

针对开放源码项目开发人员的免费PVS-Studio一文中描述了这种类型的免费许可的更多细节。

封闭源代码和学术项目。对于这类项目,基于将特殊类型的注释附加到分析的源代码上,另一种免费许可的选择是合适的。虽然这样的评论在大型企业项目中可能是不可接受的,但个别开发人员很可能会将它们添加到他们自己的项目中。这种类型的免费许可在文章“如何使用PVS-Studio for Free”中有更详细的描述。

葡萄酒检查的样本报告,以及错误的解释可以在这里找到-https://www.viva64.com/en/b/0352/。

安装strace软件包-sudo apt install straceLicense activate-pvs-studio-Analyzer Credentials [email protected] RRRR-WWWW-RRRR0-TTTD。

这是一个检查程序在处理器上花费时间的好工具。显示程序在不同线程和可用处理器之间使用的时间。还允许您检查每个函数使用的处理器节拍数。

动态和开放的代码分析器。它具有搜索内存泄漏、错误读取或应用程序剖析的能力。它在一个线程中运行代码,因此它的性能在较大的项目中不是很令人满意,但在较小的程序中工作得很好。

==50713==内存错误检测器memcheck==50713==版权所有(C)2002年至2017年,和GNU GPL';d,由Julian Seward等人撰写。=50713=使用Valgrind-3.15.0和LibVEX;使用-h重新运行版权信息==50713==命令:./rr.out==50713=50713=50713==堆摘要:==50713==退出时使用:2,400字节,2个块==50713==总堆使用量:3个分配,1个释放,分配的75,104字节==50713=50713==1块中的800字节在丢失记录中肯定丢失1/2==50713==在0x483C583:运算符NEW[](UNSIGNED LONG)(在/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)==50713==中为0x10919E:Main(In/HOME/rafal/rr.out)==50713=50713==1,600字节在丢失记录中确定丢失2/2=50713==在0x483C583:运算符NEW[。memcheck-amd64-linux.so)==50713==BY 0x1091AC:Main(In/HOME/rafal/rr.out)==50713=50713==泄漏摘要:==50713==绝对丢失:2个数据块中的2,400字节==50713==间接丢失:0数据块中的0字节==50713==可能丢失的:0数据块中的0字节==50713=仍可访问:0数据块中的0字节==50713==被禁止的:0数据块中的0字节。使用以下条件重新运行:-s==50713==错误摘要:2个上下文中的2个错误(取消显示:0,来自0)。

以图形形式显示每个时间单位的分配数量、内存泄漏和内存消耗。在检测内存泄漏方面,它比Valgrind快得多,但我猜没有以文本形式显示它们的选项。

g++rr.cpp-o rr.outheaptrace./rr.outheaptrace_gui/home/rafal/heaptrack.rr.out.50388.gz#文件名应出现在上一条命令之后。

GCC和朗都有分析器,可以在运行过程中检查程序是否有故障。与Valgrind不同的是,它们允许程序在多个线程上运行,这使得它们通常运行得更快(甚至是几倍)。在它们的帮助下编译的程序的运行速度甚至要慢几倍,占用的RAM也要多几倍。

泄漏消毒器-负责检测内存泄漏。它显示分配了多少内存以及在哪里分配了内存。此工具的开销最小。

从malloc中的#0 0x7fe4aeb98ae8(/lib/x86_64-linux-gnu/libasan.so.5+0x10dae8)分配的51个对象中的3672字节直接泄漏内存中的#1 0xd2d3c25::alloc_static(unsign long,bool)core/os/memory y.cpp:82#2 0xd2d3b24 in Operator new(unsign long,()FileAccess::Create(FileAccess::AccessType)core/os/file_access.cpp:49#5 0xd20d707 in FileAccess::create_for_path(string const&;)core/os/file_access.cpp:83#6 0xd20d9c7 in FileAccess::create/file_access.h:77#4 0xd20d2d0 in FileAccess::Create(FileAccess::AccessType)core/os/file_access.cpp:83#6 0xd20d9c7 in FileAccess::open(string const&;)

地址消毒器-负责检测值在内存中不正确位置的写入/读出,例如刚刚释放的值。

在TabContainer::_gui_input(Ref<;InputEvent>;常量中的0x61a001447e90线程T0#0 0x9f01bf7处读取大小为8的内容/gui/tab_tainer.cpp:89#1 0x2358959 in MethodBind1<;Ref<;InputEvent>;Const&;>;::Call(Object*,Variant Const**,int,Variant::CallError&;)。cpp:7630x61a001447e90位于线程T0释放的1256字节区域[0x61a001447e80,0x61a001448368]内16字节:#0 0x7f5d74ba804f in__interceptor_free(/lib/x86_64-linux-gnu/libasan.so.5+0x10c.。(object*)core/os/memory y.h:118之前由线程T0在此处分配:#0 0x7f5d74ba8448 in malloc(/lib/x86_64-linux-gnu/libasan.so.5+0x10c448)#1 0xeb7a32a in memory::alloc_static(unsign long,bool)core/os/memory y.cpp:85#2 0xeb7a226 in Operator new(。

未定义的消毒器-负责检测描述C/C++语言标准的文档中未定义的情况,例如位移位大于变量长度的值(int a=25 552)、除以零或向变量写入超出其范围的值。

Servers/visual_server.cpp:513:17:运行时错误:-2.42852超出了类型为无符号字符的可表示值的范围。摘要:UnfinedBehaviorSaniizer:orrr.cpp:10:5中的未定义行为Servers/visual_server.cpp:513:17:运行时错误:将非零偏移量4应用于空指针。

内存消毒器-仅在Clang中可用,负责检测未初始化变量的使用(从我的测试来看,它并不总是正常工作)。

==44112==警告:Memory Saniizer:Main(/HOME/rafal/rr2.out+0x4974b8)#1 0x7f86d21ec0b2 in_libc_start_main/build/glibc-YYA7BZ/glibc-2.31/csu/../csu/libc-start.c:308:16#2 0x41c26d in_start(/HOME/raal/r2.out+0x41c26d)摘要:使用未初始化的值#0x4974b8。

==44112==警告:Memory Saniizer:Main(/HOME/rafal/rr2.out+0x4974b8)#1 0x7f86d21ec0b2 in_libc_start_main/build/glibc-YYA7BZ/glibc-2.31/csu/../csu/libc-start.c:308:16#2 0x41c26d in_start(/HOME/raal/r2.out+0x41c26d)摘要:使用未初始化的值#0x4974b8。

Clang和GCC从版本10开始也有静态分析器,可以在编译期间检测潜在的错误,这不幸地延长了执行所需的时间。

rr.cpp:7:10:警告:初始化期间存储到';r';的值从不读取int*r=new int[200];^~rr.cpp:12:5:警告:赋值为垃圾或未定义的int qq=rr;^~