本文转载自微信公众号《程序喵大师》,作者程序喵大师。转载本文请联系程序大师喵公众号。大家好,我是程序喵。虽然假期快结束了,但还是有不少小伙伴问程序喵怎么还没有更新呢?我懒惰吗?其实这几天我也没闲着。一直在整理学习资料,昨晚终于搞定了,期待这两天见。好了,我们的CPP优化系列正式开始啦!在今天的文章中,我将介绍一些常用的工具,帮助大家找到代码的“臭味”(潜在的坑),进而提升代码质量。那么什么样的代码才算是高质量代码呢?我为此整理了一张脑图:如何提高代码质量,除了自身优秀的编码能力外,还需要制定代码检查流程。一般代码检查有以下几种方式:代码检查需要检查的问题是:脑图中有一些代码指标,用来量化代码质量:如果代码的圈复杂度或认知复杂度太高大,可能是功能本身实现太复杂,也可能是因为架构设计太复杂,功能太复杂。如果函数嵌套太深,意味着该函数很可能出错,需要仔细人工审核,可能需要重构函数。如果模块扇入过大,说明该模块可能是公共模块,需要人工审核接口是否稳定,或者模块承担过多责任。可以考虑遵循单一职责,分解模块的职责。如果一个模块的扇出过大,则意味着该模块依赖于多个模块。可以考虑将依赖的模块合并为一个模块,重构依赖的接口。如果类的继承树太深,考虑继承树深度是否有新的变化方向,考虑提出新的策略类,或者其他设计模式来优化继承树。如果子类过多,检查子类实现中的共通处,首先考虑提出公共中间子类,检查是否可以通过桥接模式、装饰模式、组合模式等结构模式重构代码。上述脑图需要检查的各种问题中,代码和需求偏差的问题以及代码是否符合设计问题需要人工review,成本高,其他问题可以通过工具检测。检测工具主要分为静态代码分析工具和动态代码检测工具。静态代码分析工具主要用于静态代码分析。对于静态代码分析,可以根据规则帮助检查代码缺陷。但是,该工具对于可以被检查规则覆盖的代码可以很好地工作,但是对于没有被规则覆盖的代码,它就无能为力了,而且可能会出现误报的问题。静态代码分析是保证代码质量的重要手段。据称,软件开发中约有30%-70%的代码逻辑设计和编码缺陷可以通过静态代码分析发现和修复。它会扫描程序代码,发现代码中隐藏的错误,如参数不匹配、嵌套语句不明确、递归错误、计算不合法、空指针问题、越界问题、未初始化问题、内存泄漏问题等。静态代码分析工具的优点是:自动进行静态代码分析,快速定位代码隐藏的错误和缺陷,帮助代码设计人员更专注于分析和解决代码设计缺陷,减少人工代码检查的时间,提高软件可靠性,节省实例开发成本如下:代码规范检查:由于复制粘贴,两个分支的代码完全一样voidfunc(intin,int&out){if(in>1)out++;elseout++;out++;}代码缺陷检查:uselessRAIIvoidfunc(){std::lock_guard(lk);//临时对象,语句结束后析构,误用锁...}下面是一些常见的静态代码分析工具:这里是一个commonone推荐代码质量管理平台SonarCube,SonarQube是一个代码质量管理平台(社区版免费),用于管理代码质量,会多角度维护和检测代码质量,支持多语言代码质量管理通过插件和检测。可以安装sonar-cxx插件,内置一系列C/C++代码检查工具,也可以应用于CI/CD流程,与Jenkins打通。提交代码后,可以检查代码是否有异味或者不符合规范的代码拒绝合并到master中。另一个非常有用的静态代码检测工具是Facebook的infer。它最大的优点是可以静态检测代码中隐藏的内存泄漏,免费支持Android、C、OC语言。静态代码分析工具可以帮助我们在运行前发现缺陷,只有30%-70%,但不是所有的缺陷,很多缺陷需要在运行时发现。其实我们也可以使用一些动态分析工具。通过动态分析工具,我们可以准确定位问题,误报率低,但这与测试用例强绑定。发现缺陷的比例与测试用例的覆盖率有关。代码质量意义重大。代码覆盖的意义:帮助我们找到没有被覆盖的代码,分析测试用例的设计是否充分,然后根据情况决定是否可以补充测试用例。检测代码异味,提示我们修改代码,理清代码逻辑关系,提高代码质量。代码覆盖率高并不代表代码质量就一定好,但是代码覆盖率低,代码质量就没有期望的高。它可以作为我们衡量代码质量的重要手段之一。对于没有涵盖的错误,动态分析工具无能为力。在实际工作中,我们可以将动态和静态相结合,使用多种检查方式来更有效地提高代码质量。动态分析工具可以发现程序运行时代码中的缺陷,如内存问题、数据竞争、未定义行为等。常用的工具有GCC&Clang的Santizer系列:Asan-AddressSanitizer:缓冲区溢出、内存泄漏Tsan-ThreadSanitizer:并发问题Msan-MemorySanitizer:UninitializedmemoryUbsan-UndefinedBehaviorSanitizer:UndefinedbehaviorAddfsanitize=address/memory/thread/undefined还有Valgrind工具:memchek:内存问题,包括Asan和Msanhelgrind:线程和并发问题cachegrind、callgrind、massif:帮助性能优化使用各种工具结合单元测试、功能测试、系统测试,提高覆盖率可以帮助我们发现更多的bug。以上大部分是代码分析工具。下面介绍一些性能分析工具。性能分析工具老大哥BrendanGregg的网站上有详细介绍。下面是他总结的工具图片:这张图片来自各种Linux内核。从子系统入手,总结了对各个子系统进行性能分析时可以选择的工具。其实还有一些有用的工具,图中没有提到。在这里我们将重点关注它们:gprof:gprof是GNU工具之一。编译时,它在每个函数的入口和出口添加profiling代码,运行时统计程序在用户态的执行信息中,可以得到每个函数被调用的次数,执行时间,以及调用关系,这个很容易理解。它适合寻找用户级程序的性能瓶颈,但是gprof不适合很多在内核模式下执行需要时间的程序。Oprofile:Oprofile也是一种开源分析工具。它使用硬件调试寄存器来统计信息。profiling的开销比较小,可以对内核进行profile。它有很多统计信息,比如缓存未命中率、内存访问信息、分支预测错误率等,这些是gprof无法获取的,但是对于函数调用次数它也无能为力。总之,gprof简单,适合寻找用户级程序的瓶颈,而Oprofile稍微复杂一点,但获取的信息较多,更适合调试系统软件。gperftools:Google出品,值得信赖。它提供了整个程序的热点分布图,找到性能瓶颈,进而进行针对性的性能优化,如图:我们在平时的编程过程中,可能会多次使用某些时间API来计算函数消耗,使用时,您可以看看我的这篇文章:《详细介绍下C/C++时间相关的那些函数》什么API用起来效率更高?可以看下图:图中的rdtsc使用起来比较麻烦,并不适用于所有平台和编译器。其他人可以按需使用。关于性能分析工具,程序喵整理了一个很详细的脑图(精华都在脑图中),按性能指标分类,不同指标分析用什么工具,图里都有,目录如下如下:最后,公众号后台回复“性能分析工具”,获取完整高清PDF文件~如果喜欢本文,请点赞、观看、支持~谢谢!参考https://stackoverflow.com/questions/375913/how-can-i-profile-c-code-running-on-linuxhttps://zh.wikipedia.org/wiki/%E6%80%A7%E8%83%BD%E5%88%86%E6%9E%90https://www.cnblogs.com/bangerlee/archive/2012/08/30/2659435.htmlhttp://www.brendangregg.com/linuxperf.htmlhttps://www.cnblogs.com/youxin/p/7988479.htmlhttps://www.agner.org/optimize/https://zhuanlan.zhihu.com/p/141694060https://www.wyyuan.com/2018/11/06/%E8%AE%A4%E7%9F%A5%E5%A4%8D%E6%9D%82%E5%BA%A6/http://bitjoy.net/2017/02/07/introduction-to-performance-analysis-tools-in-linux/