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

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

Здесь есть аналогичный вопрос с большей активностью: stackoverflow.com/questions/4813947/…

Mr Shark 10.02.2011 23:05
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
68
1
35 368
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Инструмент покрытия Яблочко поможет. Однако это не бесплатно.

Стоит ли денег? Есть опыт работы с этим? У них есть пробная версия, так что я могу ее проверить, если она сработает, мы сможем ее купить :)

Nazgob 23.10.2008 13:34

Да .. Я использовал на платформе Symbian ... Его определенно стоит купить

Ashwin 24.11.2008 14:22
Ответ принят как подходящий

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

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

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

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

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

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

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

Я все еще придерживаюсь компиляторов Sun C++, но у нас идет миграция gcc, так что я собираюсь попробовать это. Спасибо.

Nazgob 23.10.2008 13:43

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

Arun 15.01.2018 20:58

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

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

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

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

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

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

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

Этот ответ больше не соответствует тому факту, что параметр -Wunreachable-code был удален из gcc. gcc.gnu.org/ml/gcc-help/2011-05/msg00360.html

philippe lhardy 16.12.2013 03:19

Стыд. Для многих целей обнаружение «нестабильного» мертвого кода все же лучше, чем ничего. Помимо всего прочего, идеальное обнаружение мертвого кода в целом невозможно (проблема остановки), поэтому все знают, что какой бы инструмент они ни использовали, он несовершенен. Предположительно, кого-то действительно волнует, что он более несовершенный с -O0, чем с -O3, или не хочет новых предупреждений, когда оптимизатор улучшается.

Steve Jessop 16.12.2013 03:42

Тем не менее, если в вашем коде нет новых функций, вы все равно можете использовать старый gcc в качестве инструмента статического анализа. Так что мой ответ не ошибочен. Я знаю ;-)

Steve Jessop 16.12.2013 03:48

И Mozilla, и Открытый офис имеют собственные решения.

Обе ссылки сейчас недоступны. Кто-нибудь может обновить?

syam 17.04.2017 05:15

Я переключил первую ссылку с сообщения в блоге на (надеюсь, более длительную) страницу документации. Ссылка "Открыть офис" работает.

Max Lybbert 17.04.2017 08:19

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 () (точка a), даже если она недоступна в этом файле. Такое поведение является правильным, хотя и разочаровывающим, поскольку компилятор не может знать, что функция foo () не объявлена ​​как extern в каком-то другом модуле компиляции и не вызывается оттуда; только компоновщик может быть уверен.

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

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

DMS также анализирует C++ на различных диалектах (EDIT, февраль 2014 г .: включая версии C++ 14 для MS и GCC [ИЗМЕНИТЬ ноябрь 2017 г .: теперь C++ 17]) и строит все необходимые таблицы символов. Отследить мертвые ссылки с этого момента будет просто. DMS также можно использовать для их удаления. См. http://www.semanticdesigns.com/Products/DMS/DMSToolkit.html

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

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

Другие вопросы по теме