85

我们有一个相当大的代码库,400K LOC 的 C++,代码重复是个问题。是否有任何工具可以有效地检测重复的代码块?

理想情况下,这将是开发人员可以在开发过程中使用的东西,而不是偶尔运行以查看问题所在。如果我们可以将这样的工具与 CruiseControl 集成,以便在每次签到后提供报告,那也很好。

前段时间我看过Duploc,它显示了一个很好的图表,但需要一个 smalltalk 环境才能使用它,这使得自动运行它相当困难。

免费工具会很好,但如果有一些好的商业工具我也会感兴趣。

4

13 回答 13

39

Simian检测 C++ 项目中的重复代码。

更新:也适用于 Java、C#、C、COBOL、Ruby、JSP、ASP、HTML、XML、Visual Basic、Groovy 源代码甚至纯文本文件

于 2008-10-10T14:40:56.007 回答
21

我使用了 PMD 的 Copy-and-Paste-Detector并通过使用以下包装脚本将其集成到 CruiseControl 中(确保在类路径中有 pmd jar)。

我们的支票每晚运行一次。如果您希望将输出限制为仅列出当前更改集中的文件,则可能需要一些自定义编程(想法:检查全部并仅列出涉及已更改文件之一的重复项。您必须检查所有文件,因为更改可以使用来自未更改文件的一些代码)。应该可以通过使用 XML 输出并解析结果来实现。完成后不要忘记发布该脚本;)

对于初学者,“文本”输出应该没问题,但您会希望以用户友好的方式显示结果,为此我使用 perl 脚本从 CPD 的“xml”输出生成 HTML 文件。这些可以通过将它们发布到 Cruise 的报告 jsp 所在的 tomcat 来访问。开发人员可以从那里查看它们并查看其肮脏的黑客攻击的结果:)

它运行得非常快,在 150 KLoc 代码上不到 2 秒(空行和注释不计入该数字)。

重复检查.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>

于 2008-11-24T17:12:54.837 回答
7

duplo似乎是 Duploc 中使用的算法的 C 实现。编译和安装很简单,虽然选项有限,但它似乎或多或少是开箱即用的。

于 2008-12-17T04:54:12.637 回答
6

这些 Debian 软件包似乎做了以下事情

PS 对于所有与查找 [near] 重复相关的工具,都应该有一个debtags标签。(但它会叫什么?)

于 2012-03-13T22:04:33.160 回答
5

查看PMD 项目

我从来没有用过,但一直想用。

于 2008-10-10T14:43:34.957 回答
3

好吧,你可以每晚在你的源代码库上运行一个克隆检测器。

许多克隆检测器通过比较源代码行来工作,并且只能找到完全相同的重复代码。

上面的 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-日标。

该站点有多个克隆检测运行示例报告,包括一份针对 C++ 的报告。

编辑 2014 年 2 月:现在处理所有 C++14。

于 2009-06-28T19:27:51.353 回答
2

CCFinderX是一个免费的(供内部使用)克隆代码检测器,支持多种编程语言(Java、C、C++、COBOL、VB、C#)。

于 2008-10-11T04:55:41.257 回答
2

ConQAT是一个很棒的工具,它支持 C++ 代码分析。可以找到忽略空格的重复项。具有非常方便的 gui 和控制台界面。由于它的灵活性,它不容易设置。我发现这篇博文对于设置 c++ 项目非常有用

于 2013-08-03T14:48:37.667 回答
2

Same ( http://sourceforge.net/projects/same/ ) 非常简单,但它适用于文本行而不是标记,如果您使用的语言不受更高级的克隆之一支持,这很有用发现者。

于 2009-08-25T16:10:39.957 回答
2

您可以使用我们的SourceMeter工具来检测代码重复。它是一个命令行工具(与编译器非常相似),因此您可以轻松地将其集成到持续集成工具中,例如您提到的CruiseControl或Jenkins

于 2015-07-31T16:12:31.923 回答
1

查找“相同”的代码片段相对容易,现有的工具已经可以做到这一点(参见其他答案)。

有时这是一件好事,有时不是;如果在“级别”太精细,它可能会拖慢开发时间;即试图重构这么多代码,你会失去你的目标(并且可能破坏你的里程碑和时间表)。

更难的是在没有适当文档的情况下找到多个功能/方法,它们做同样的事情但具有不同(但相似)的输入和/或算法。

如果您必须使用两种或不同的方法来做同样的事情,而程序员尝试修复一个实例但忘记(或不知道它们存在)修复其他实例,您将增加软件的风险。

于 2008-11-24T17:25:06.700 回答
1

还有支持 Java、C#、C++、C、Objective-C、JavaScript 的Simian ...

Hudson支持它(如 CPD)。

除非你是一个开源项目,否则你必须为 Simian付费

于 2010-07-15T22:18:53.353 回答
-3

TeamCity有一个强大的 .NET 和 java 代码复制引擎,可以毫不费力地作为构建系统的一部分运行。

于 2008-11-17T16:20:28.750 回答