Обнаружение мертвого кода в устаревшем проекте C/С++

Как вы думаете о детектировании мертвого кода в коде C/С++? У меня есть довольно большая база кода для работы и по крайней мере 10-15% - это мертвый код. Есть ли какой-либо инструмент на основе Unix для определения этих областей? Некоторые фрагменты кода по-прежнему используют много препроцессора, может ли автоматизированный процесс обрабатывать это?

Ответ 1

Вы можете использовать инструмент анализа покрытия кода для этого и искать неиспользуемые места в вашем коде.

Популярным инструментом для gcc toolchain является gcov вместе с графическим интерфейсом lcov (http://ltp.sourceforge.net/coverage/lcov.php).

Если вы используете gcc, вы можете скомпилировать его с поддержкой gcov, который включен флагом '--coverage'. Затем запустите приложение или запустите тестовый пакет с помощью этой сборки с поддержкой gcov.

В основном gcc будет выделять некоторые дополнительные файлы во время компиляции, и приложение также будет выдавать некоторые данные покрытия во время работы. Вы должны собрать все эти файлы (.gcdo и .gcda). Я не буду здесь подробно, но вам, вероятно, нужно установить две переменные среды для сбора данных о покрытии разумным способом: GCOV_PREFIX и GCOV_PREFIX_STRIP...

После запуска вы можете объединить все данные покрытия и запустить его через lcov toolsuite. Также возможно объединение всех файлов покрытия из разных тестовых прогонов, хотя и немного вовлеченных.

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

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

Ответ 2

Скомпилируйте его под gcc с кодом -Wunreachable.

Я думаю, что чем более поздняя версия, тем лучше результаты, которые вы получите, но я могу ошибаться в своем впечатлении, что это то, над чем они активно работали. Обратите внимание, что это анализ потока, но я не думаю, что он говорит вам о "коде", который уже мертв к тому времени, когда он покидает препроцессор, потому что это никогда не анализируется компилятором. Он также не обнаруживает, например. экспортируемые функции, которые никогда не вызываются, или специальный код обработки случая, который так просто случается, потому что ничего не вызывает функцию с этим параметром - для этого вам требуется покрытие кода (и запускайте функциональные тесты, а не модульные тесты. предполагается, что он имеет 100% -ный охват кода и, следовательно, выполняет коды кода, которые "мертвы" в отношении приложения). Тем не менее, с учетом этих ограничений, это простой способ начать поиск наиболее полных подпрограмм в базе кода.

В этом совете CERT перечислены некоторые другие инструменты для обнаружения статического мертвого кода

Ответ 3

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

Если вам не так повезло, вам может понадобиться изучить инструменты анализа исходного кода, такие как SciTools 'Понять, что может помочь вам проанализируйте свой код, используя множество встроенных аналитических отчетов. Мой опыт работы с этим инструментом датируется 2 года назад, поэтому я не могу дать вам много подробностей, но помню, что у них была впечатляющая поддержка с очень быстрыми моментами исправления ошибок и ответами на вопросы.

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

Если это вам тоже не поможет, и вы особенно заинтересованы в обнаружении мертвого кода, связанного с препроцессором, я бы порекомендовал вам опубликовать дополнительную информацию о коде. Например, если в основном это связано с различными комбинациями параметров #ifdef, вы можете писать сценарии для определения (комбинаций) настроек и выяснить, какие комбинации никогда не были построены и т.д.

Ответ 5

g++ 4.01 -Wunreachable-code предупреждает о коде, недоступном внутри функции, но не предупреждает о неиспользуемых функциях.

int foo() { 
    return 21; // point a
}

int bar() {
  int a = 7;
  return a;
  a += 9;  // point b
  return a;
}

int main(int, char **) {
    return bar();
}

g++ 4.01 выдает предупреждение о точке b, но ничего не говорит о foo() (point a), хотя в этом файле недоступен. Такое поведение является правильным, хотя и неутешительным, поскольку компилятор не может знать, что функция foo() не объявлена ​​extern в какой-либо другой компиляционной единице и вызвана оттуда; может быть уверен только в компоновщике.

Ответ 6

Только для кода C и предполагая, что исходный код всего проекта доступен, запустите анализ с помощью инструмента Open Source Frama-C. Любой оператор программы, отображающий красный цвет в графическом интерфейсе, является мертвый код.

Если у вас проблемы с "мертвым кодом", вы также можете быть заинтересованы в удаление "запасного кода", код, который выполняется, но не способствуют достижению конечного результата. Это требует, чтобы вы предоставили точная моделировка функций ввода-вывода (вы не захотите для удаления вычислений, которые кажутся "запасными", но который используется в качестве аргумента для printf). Frama-C имеет возможность указывать запасной код.

Ответ 7

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

Мы использовали инструмент DMS Software Reengineering Toolkit для реализации именно этого для Java-кода, путем разбора всех задействованных единиц компиляции, создания таблиц символов для всех и преследования всех ссылок. Определение верхнего уровня без ссылок и никаких претензий на внешний элемент API не работает. Этот инструмент также автоматически удаляет мертвый код, и в конце вы можете выбрать то, что хотите: отчет мертвых объектов или код, лишенный этих объектов.

DMS также анализирует С++ во множестве диалектов (EDIT Feb 2014: включая версии MS и GCC для С++ 14 [EDIT Nov 2017: теперь С++ 17]) и создает все необходимые таблицы символов. Отслеживание мертвых ссылок было бы прямолинейным с этой точки. DMS также может использоваться для их снятия. См. http://www.semanticdesigns.com/Products/DMS/DMSToolkit.html

Ответ 8

Bullseye инструмент покрытия поможет. Это не бесплатно, хотя.