Программное обеспечение для обнаружения клонов кода

Я ищу простой инструмент, который может идентифицировать похожие части в одном или нескольких файлах.

Я работаю над довольно старой кодовой базой, где разработчики часто использовали копирование и вставку. В конце концов, у нас есть сотни C-файлов длиной около 10 000 строк.

Я хотел бы идентифицировать подобный код с помощью не слишком сложного инструмента.

Какое программное обеспечение или инструмент я могу использовать для этой работы?

Первый подход будет состоять в том, чтобы рассмотреть один файл из 10 000 строк, который содержит функции C. Внутри этих длинных функций я могу вручную определить блоки, которые очень похожи на некоторые другие. Разница иногда заключается в имени переменных foo_m0и/ foo_m1или индексе таблицы foo[0]и foo[1].

В таких длинных файлах не всегда легко указать на эти участки похожего кода. Использование инструмента, который может определить самый длинный избыточный блок и наиболее повторяющийся в файле, будет очень полезным для планирования действий по рефакторингу.

Обратите внимание, что существует программное обеспечение/веб-сайты, которые обнаруживают плагиат. Может быть, это подход...
Почему вы думаете, что это "просто"?
Под простым я подразумеваю не тяжелое программное обеспечение.
Я создаю эти инструменты. Вы не можете избежать «тяжелого программного обеспечения», чтобы сделать это правильно. Почему тебя это беспокоит?

Ответы (4)

Я использовал Simian , который

выявляет дублирование в Java, C#, C, C++, COBOL, Ruby, JSP, ASP, HTML, XML, Visual Basic, исходном коде Groovy и даже в текстовых файлах

Это коммерческое программное обеспечение с различными лицензиями . и он может игнорировать идентификаторы, фигурные скобки и т. д. во время сравнения, поэтому вы можете найти не только точные дубликаты, но и структурные дубликаты.

Он работал нормально, но, кажется, всегда немного отставал от современного уровня техники (например, поддержка запросов LINQ в C#) в то время, когда я его использовал. Поэтому я сомневаюсь, что это будет работать очень хорошо, если вы используете последний стандарт C++. Тем не менее, это будет хорошо работать.

Я не уверен, как он интегрируется в вашу IDE. Его можно было использовать в C# с плагином ReSharper под названием Agent Ralph . Возможно, что-то подобное существует для C++.

Позвольте мне порекомендовать эти 3 инструмента, которые могут решить вашу проблему:

http://www.solidsourceit.com/products/SolidSDD-code-duplication-cloning-analysis.html - лучший, но не бесплатный (на самом деле немного дороже)

http://www.harukizaemon.com/simian/

http://duplo.sourceforge.net/

Кажется, что solidsource не работает. Я не могу создать пробную лицензию и не получаю ответов по электронной почте.

Существует ряд инструментов, которые могут помочь найти прямые копии/дубликаты кода в коде C/CPP, как указано в ответах на этот вопрос о переполнении стека. Как уже отмечалось, многие механизмы обнаружения терпят неудачу просто из-за простых изменений отступов.

Лично я обнаружил, что одним из лучших механизмов обнаружения дублирования кода является рефакторинг больших файлов в файлы меньшего размера, сгруппированные по назначению и дающие значимые имена, с точки зрения обслуживания и времени компиляции, это почти всегда стоит делать в любом случае. Вскоре вы обнаружите, что нужное вам имя уже существует, и тогда вы можете либо использовать только одну версию, либо обобщить/абстрагировать код. Я видел примеры, когда то, что должен был делать код, было идентичным, за исключением значений некоторых индексов, на самом деле в случае, о котором я думаю, было несколько копий, сделанных в разное время, некоторые отсутствующие исправления ошибок, которые были найдены, обобщение может заключаться в передаче перечисления для указания варианта использования и использовании его для выбора индекса (ов) или путем прямой передачи индекса и проверки диапазона перед использованием.

Это может работать для проектов скромного размера, но я сомневаюсь, что вы можете вручную, реалистично «рефакторить» 100K SLOC или код таким образом, и я сомневаюсь, что ваш босс позволит вам. В масштабе вам нужны инструменты. Правильные инструменты могут обобщать фрагменты кода.

Наш инструмент CloneDR может сделать это для больших баз кода со многими файлами (или только с одним файлом, если вы настаиваете). Он находит:

  • точные клоны . Использование языковой структуры (AST) для управления процессом сопоставления, гарантируя, что обнаруженные клоны являются разумными блоками кода. Это также означает, что он найдет клоны в любой языковой структуре (целые функции, последовательности операторов, большие выражения и т. д.), несмотря на измененную компоновку кода (отступы, пробелы, наличие/отсутствие комментариев, константы с одинаковым значением, но с другим основанием). , ...). Если есть набор из нескольких (или многих!) блоков кода, являющихся клонами, то сообщается набор, а не пары. Точные клоны сообщаются по точному местоположению источника.
  • почти клоны промаха , включая выражения, замененные именами переменных, и наоборот, как OP дает в качестве примеров, и во многих случаях места, где операторы были вставлены или удалены. (Это часто обнаруживает сломанные клоны, где исправление не распространялось, как обсуждалось Стивом Барнсом в его ответе). Клоны, находящиеся на грани промаха, сообщаются по местоположению, с параметрами, показывающими, чем они отличаются, и как параметры могут быть связаны для создания точных клонов в исходном коде. Это почти объявление подпрограммы для общности.

CloneDR обычно находит 10+% дублированного кода в относительно хорошо спроектированном программном обеспечении. Эти цифры могут быть значительно больше в неаккуратном исходном коде (у нас есть реальный пример 100K SLOC COBOL, который на 55%+ дублирует код, эй).

CloneDR использует анализатор с точностью до языка для обнаружения структуры кода. Существуют версии для многих языков, включая различные диалекты C (через C11) и C++ (через C++14 с появлением C++17) и особенно включая диалекты, специфичные для MS. [Мы пытаемся поддерживать скорость нашего языкового фронта. CloneDR работает для С# 6, включая команды LINQ, упомянутые в другом ответе].

Настроить CloneDR для запуска довольно просто: вы создаете файл проекта, в котором перечислены исходные файлы, которые вы хотите проанализировать, плюс несколько параметров, которые определяют, что означает «почти промах» (x+y — это клон a+1 с переменной заменой , но вы действительно не хотите их видеть).

Из-за сложностей с анализом исходного кода с директивами препроцессора без их расширения для C и C++ вам, возможно, придется настроить CloneDR для вашей конкретной кодовой базы, сообщив ему о ваших более вопиющих макросах или условных выражениях, которые затрудняют автономный анализ. Это можно сделать для систем с миллионом строк с довольно скромными усилиями. C обычно требует немного усилий. С++ часто этого не делает; Программисты на C++ редко используют препроцессор. Другие языки, поддерживаемые CloneDR без препроцессоров, не нуждаются в этом специальном шаге.

На сайте есть примеры отчетов об обнаруженных клонах для разных языков. Загружаемая демонстрация определит все клоны (даже в большой системе) и предоставит анализ того, насколько клонировано анализируемое программное обеспечение; он также покажет некоторые из клонов.

Поскольку это мой инструмент, не принимайте это как рекомендацию; просто документирует его существование. Он основан на моем многолетнем опыте написания кода, и есть технический документ, описывающий, как он работает: Clone Detection Using Abstract Syntax Trees .