翻译《有关编程、重构及其他的终极问题?》——40.开始使用静态代码分析
标签(空格分隔):翻译 技术 C/C++
作者:Andrey Karpov
翻译者:顾笑群 - Rafael Gu
最后更新:2018年09月28日
40.开始使用静态代码分析
阅读一位静态代码分析器的开发者写的一大段文字,却不知道如何使用静态代码分析,这是非常奇怪的。所以这次我们就来说说如何使用静态代码分析。
下面的代码摘自Haiku项目(从BeOS项目继承而来)。这段代码包含的错误被PVS-Studio分析器诊断为:There are identical sub-expressions to the left and to the right of the ‘<’ operator: lJack->m_jackType < lJack->m_jackType(译者注:大意为“<”操作符两边的变量是一样的)。
int compareTypeAndID(....)
{
....
if (lJack && rJack)
{
if (lJack->m_jackType < lJack->m_jackType)
{
return -1;
}
....
}
解释
这只是一个平常的打字错误,在表达式的右边,理应是rJack,却被写成了lJack。
这种打字错误的确比较简单,但实际产生这种情况的原因却很复杂,这可能牵扯到编程风格等一系列问题,但即使知道什么问题导致,也无助于解决。大家就是这么眼睁睁的犯下类似错误,你却无能为力。
很重要的是,我们要意识到,这种问题不是特定的人或者特定的项目才有。毫无疑问,所有人都会犯类似错误,即使在正规项目总的专家们也会犯。我说这些是有证据的,你可以看到类似最简单的A == A这种打字错误,都可以在如下项目中被发现:Notepad++,WinMerge,Chromium,Qt,Clang,OpenCV,TortoiseSVN,LibreOffice,CoreCLR,Unreal Engine 4等。
因此这类问题是真实存在的,不光是在实验室中的学生项目中。当一些人告诉我说那些有经验的程序员不会犯下这类错误时,我就给他们发送了这个链接。
正确的代码
if (lJack->m_jackType < rJack->m_jackType)
建议
首先,让我们说一些无用的敲门:
- 编程时要很小心,不要让错误偷溜进你的代码(说的好听,但毫无用处)
- 使用好的代码风格(事实上,不存在一种编程风格可以避免变量名的拼写错误)
那么,那些是真正有用的呢:
- 代码复查(译者注:就是我们一般直接使用英文说的code review)
- 单元测试(TDD)(译者注:TDD就是敏捷开发中的测试驱动)
- 静态代码分析
我不得不说,以上每种策略都有它的长处和短处,这就是为何最好、最有效的办法就是把他们一起使用。
代码复查能帮助我们找出大量的不同错误,并且,能帮助我们提高代码的可阅读性。但不幸的是,这种策略的代价时非常昂贵的,而且比较无聊,最后也不能给出一个完全有效复查的保证。比如,下面的代码打字错误就非常难以被发现:
qreal l = (orig->x1 - orig->x2)*(orig->x1 - orig->x2) +
(orig->y1 - orig->y2)*(orig->y1 - orig->y1) *
(orig->x3 - orig->x4)*(orig->x3 - orig->x4) +
(orig->y3 - orig->y4)*(orig->y3 - orig->y4);
理论上,单元测试可以拯救我们。但只在理论上有这个可能。因为实际上,检查所有的执行路径是不现实的;除此之外,一个测试本身也有可能包含错误:)
静态代码分析器也会有问题,而且也不是智能化的。一个分析器可能忽略一些错误,另一方面,还有可能显示一些实际上正确的错误。但除了这些问题外,静态代码分析器其实能算得上是一种真正有用的工具,它可以在初期就可以发现大量的错误。
一个静态代码分析器可以被用来做性价比高的代码复查。使用程序而非程序员来做代码复查,然后更全面的建议检查特定的代码片段。
当然,我很愿意建议大家使用我们开发的PVS-Studio代码分析器,但这并非世界上唯一一款代码分析器,还有其他很多免费或付费的同类工具。比如你可以尝试使用一下免费、开源的分析器Cppcheck。你可以在Wikipedia上找到大量的同类工具:静态代码分析工具列表。
注意:
- 错误的使用一个静态代码分析器可能反而会让你头疼。比如一种典型的错误就是“尽量多的得到检查结果的警告消息”。这是我经常收到的建议,所以就得到了一个很多很多的错误警告列表,对于这种情况,这两篇文章A和B会有帮助。
- 一个静态代码分析器应该被当成基本工具使用,而不仅仅是每次使用一下,或者当项目情况越来越糟糕了才使用。相关的的解释可以看C和D这两篇文章。
真的,尝试用用静态代码分析工具吧,你会喜欢上他们的,他们是非常好的清洁工具。
最后,我很愿意推荐大家读一下John Carmack的文章:静态代码分析。