我们有一个相当大的代码库,C ++的LOC为400K,并且代码重复是一个问题。是否有任何工具可以有效地检测重复的代码块?
理想情况下,开发人员可以在开发过程中使用它,而不仅仅是偶尔运行以查看问题所在。如果我们可以将这样的工具与CruiseControl集成在一起,在每次签入后提供报告,那也很好。
我前段时间看过Duploc,它显示了一个漂亮的图形,但是需要一个Smalltalk环境才能使用它,这使得自动运行非常困难。
免费工具会很好,但是如果有一些好的商业工具,我也会感兴趣。
我们有一个相当大的代码库,C ++的LOC为400K,并且代码重复是一个问题。是否有任何工具可以有效地检测重复的代码块?
理想情况下,开发人员可以在开发过程中使用它,而不仅仅是偶尔运行以查看问题所在。如果我们可以将这样的工具与CruiseControl集成在一起,在每次签入后提供报告,那也很好。
我前段时间看过Duploc,它显示了一个漂亮的图形,但是需要一个Smalltalk环境才能使用它,这使得自动运行非常困难。
免费工具会很好,但是如果有一些好的商业工具,我也会感兴趣。
Answers:
我使用了PMD的“复制并粘贴检测器”,并通过使用以下包装器脚本将其集成到CruiseControl中(请确保在类路径中有pmd jar)。
我们的支票每晚进行。如果希望将输出限制为仅列出当前更改集中的文件,则可能需要进行一些自定义编程(想法:检查全部并仅列出涉及其中一个更改文件的重复项。您必须检查所有文件,因为更改可能会使用来自未更改文件的一些代码)。应该可以通过使用XML输出并解析结果来实现。完成后不要忘记发布该脚本;)
对于初学者,“文本”输出应该可以,但是您将希望以一种用户友好的方式显示结果,为此,我使用perl脚本从CPD的“ xml”输出中生成HTML文件。通过将它们发布到Cruise的报告jsp所在的tomcat中,可以访问这些文件。开发人员可以从那里查看它们,并查看其恶意入侵的结果:)
它运行非常快,在150 KLoc代码上不到2秒(空行和注释未计入该数字)。
plicatecheck.xml:
<project name="duplicatecheck" default="cpd">
<property name="files.dir" value="dir containing your sources"/>
<property name="output.dir" value="dir containing results for publishing"/>
<target name="cpd">
<taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask"/>
<cpd minimumTokenCount="100"
language="cpp"
outputFile="${output.dir}/duplicates.txt"
ignoreLiterals="false"
ignoreIdentifiers="false"
format="text">
<fileset dir="${files.dir}/">
<include name="**/*.h"/>
<include name="**/*.cpp"/>
<!-- exclude third-party stuff -->
<exclude name="boost/"/>
<exclude name="cppunit/"/>
</fileset>
</cpd>
</target>
好了,您可以每晚在源代码库上运行一个克隆检测器。
许多克隆检测器通过比较源代码行来工作,并且只能找到确切的重复代码。
上面的CCFinder通过比较语言标记来工作,因此它对空格的变化不敏感。如果只有单个标记更改(例如,将克隆中的变量X更改为Y),则它可以检测到作为原始代码变体的克隆。
理想情况下,您需要的是上面的方法,但是能够找到允许变异相对任意的克隆,例如,用表达式替换变量,用语句替换语句等。
我们的CloneDR克隆检测器可用于Java,C#,C ++,COBOL,VB.net,VB6,Fortran和其他多种语言。可以在以下位置看到它:http : //www.semdesigns.com/Products/Clone/index.html
除了能够处理多种语言外,CloneDR引擎还可以处理各种输入编码样式,包括ASCII,ISO-8859-1,UTF8,UTF16,EBCDIC,多种Microsoft编码和(日语)Shift- JIS。
该站点有几个克隆检测运行示例报告,其中一个针对C ++。
编辑2014年2月:现在处理所有C ++ 14。
CCFinderX是一个免费的(内部使用的)克隆代码检测器,它支持多种编程语言(Java,C,C ++,COBOL,VB,C#)。
查找“完全相同”的代码段相对容易,已有的工具已在执行此操作(请参阅其他答案)。
有时候这是一件好事,有时却不是。如果做得太“精细”,它可能会缩短开发时间;例如,尝试重构大量代码,您就失去了目标(并可能破坏了里程碑和时间表)。
更加困难的是,在没有适当文档的情况下,找到执行相同功能但具有不同(但相似)输入和/或算法的功能/方法。
如果您必须使用两种或不同的方法来完成相同的事情,而程序员尝试修复一个实例却忘记(或不知道它们存在)来修复另一个实例,则可能会增加软件的风险。
相同(http://sourceforge.net/projects/same/)非常简单,但是它适用于文本行而不是标记,如果您使用的是一种较高级的克隆所不支持的语言,这将非常有用发现者。
ConQAT是支持C ++代码分析的出色工具。可以找到忽略空格的重复项。具有极为方便的GUI和控制台界面。由于具有灵活性,因此设置起来并不容易。我发现这篇博客文章对于设置c ++项目非常有用。
您可以使用我们的SourceMeter工具来检测代码重复。它是一个命令行工具(非常类似于编译器),因此您可以轻松地将其集成到持续集成工具中,例如您提到的CruiseControl或Jenkins。
TeamCity具有适用于.NET和Java的强大代码复制引擎,可以轻松地在构建系统中运行。