Обнаружение лишних включений в C/C++?

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

Есть ли какой-нибудь инструмент, который может обнаруживать лишние директивы #include и подсказывать, какие из них я могу безопасно удалить?
Может ли это сделать?

Ответ 1

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

Ответ 2

Google cppclean (ссылки на: скачать, документация) может найти несколько категорий проблем С++, и теперь он может найти лишние #includes.

Там также есть инструмент, основанный на Clang, include-what-you-use, который может это сделать. include-what-you-use может даже предлагать передовые декларации (так что вам не нужно так много #include) и, возможно, очистите свои #includes для вас.

В текущих версиях Eclipse CDT также встроена эта функция: переход в меню "Источник" и нажатие кнопки "Упорядочить" будет в алфавитном порядке добавлять # include, добавлять любые заголовки, которые Eclipse думает, что вы используете, без прямого их включения, и комментирует любые заголовки, которые, по вашему мнению, вам не нужны. Однако эта функция не на 100% надежна.

Ответ 3

Также проверьте include-what-you-use, который решает подобную проблему.

Ответ 4

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

Lint - это скорее средство проверки стиля и, конечно же, не будет иметь этой полной возможности.

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

Ответ 5

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

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

Ответ 6

CScout браузер рефакторинга может обнаруживать избыточные директивы include в коде C (к сожалению, не С++). Вы можете найти описание того, как это работает в этой статье в журнале.

Ответ 7

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

Пусть он работает ночью, а на следующий день у вас будет 100% правильный список включенных файлов, которые вы можете удалить.

Иногда грубая сила работает: -)


изменить:, а иногда нет:-). Вот немного информации из комментариев:

  • Иногда вы можете удалить два файла заголовка отдельно, но не оба вместе. Решение состоит в том, чтобы удалить файлы заголовков во время прогона и не возвращать их обратно. Это найдет список файлов, которые можно безопасно удалить, хотя может быть решение с большим количеством файлов для удаления, которые этот алгоритм не найдет. (это жадный поиск по пространству включенных файлов для удаления. Он найдет только локальный максимум)
  • Могут быть незначительные изменения в поведении, если у вас есть некоторые макросы, переопределенные по-разному в зависимости от некоторых #ifdefs. Я думаю, что это очень редкие случаи, и тесты Unit, которые являются частью сборки, должны улавливать эти изменения.

Ответ 8

Извините (пере) пост здесь, люди часто не раздают комментарии.

Посмотрите мой комментарий на crashmstr, FlexeLint/PC-Lint сделает это за вас. Информационное сообщение 766. Обсуждается это в разделе 11.8.1 моего руководства (версия 8.0).

Кроме того, , и это важно, продолжайте повторять, пока сообщение не исчезнет. Другими словами, после удаления неиспользуемых заголовков повторно запустите lint, после того, как вы удалите ненужные заголовки, больше файлов заголовков могут стать "ненужными". (Это может звучать глупо, читать его медленно и анализировать, это имеет смысл.)

Ответ 9

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

Ответ 10

Если вы используете Eclipse CDT, вы можете попробовать http://includator.com, который является бесплатным для бета-тестеров (на момент написания этой статьи) и автоматически удаляет лишние # включает или добавляет недостающие. Для тех пользователей, которые имеют FlexeLint или PC-Lint и используют Elitpse CDT, http://linticator.com может быть вариантом (также бесплатным для бета-теста). Хотя он использует анализ Lint, он обеспечивает быстрые исправления для автоматического удаления лишних операторов #include.

Ответ 11

Я пробовал использовать Flexelint (unix-версия PC-Lint) и имел несколько смешанные результаты. Скорее всего, потому, что я работаю над очень большой и узловатой базой кода. Я рекомендую внимательно изучить каждый файл, который сообщается как неиспользуемый.

Основное беспокойство - ложные срабатывания. Несколько включений одного и того же заголовка сообщаются как ненужный заголовок. Это плохо, поскольку Flexelint не сообщает вам, в какую строку заголовок включен или где он был включен ранее.

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

В A.hpp:

class A { 
  // ...
};

В B.hpp:

#include "A.hpp

class B {
    public:
        A foo;
};

В C.cpp:

#include "C.hpp"  

#include "B.hpp"  // <-- Unneeded, but lint reports it as needed
#include "A.hpp"  // <-- Needed, but lint reports it as unneeded

Если вы слепо следите за сообщениями из Flexelint, вы отбросите свои зависимости #include. Есть больше патологических случаев, но в основном вам нужно будет проверить заголовки самостоятельно для достижения наилучших результатов.

Я очень рекомендую эту статью на Физическая структура и С++ из блога Игры изнутри. Они рекомендуют комплексный подход к очистке #include mess:

Руководство по

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

  • Каждый файл cpp сначала содержит свой заголовочный файл. [Надрез]
  • Заголовочный файл должен содержать все файлы заголовков, необходимые для его анализа. [Надрез]
  • Заголовочный файл должен иметь минимальное количество файлов заголовков, необходимых для его анализа. [Надрез]

Ответ 12

В этой статье объясняется метод удаления #include с помощью разбора Doxygen. Это просто perl script, поэтому он довольно прост в использовании.

Ответ 13

Существует бесплатный инструмент Включить Watcher Dependencies File, который можно интегрировать в визуальную студию. Он показывает лишние # включает красный.

Ответ 14

Чтобы завершить это обсуждение, препроцессор С++ завершен. Это семантическое свойство, независимо от того, является ли включение излишним. Следовательно, из теоремы Райса следует, что неразрешимо, является ли включение избыточным или нет. Там НЕ МОЖЕТ быть программой, которая (всегда правильно) определяет, является ли добавление излишним.

Ответ 15

Возможно, немного поздно, но однажды я нашел WebKit perl script, который сделал именно то, что вы хотели. Мне понадобится адаптация, я верю (я не очень разбираюсь в perl), но он должен сделать трюк:

http://trac.webkit.org/browser/branches/old/safari-3-2-branch/WebKitTools/Scripts/find-extra-includes

(это старая ветка, потому что у trunk больше нет файла)

Ответ 16

Существует два типа избыточных файлов #include:

  • Файл заголовка, который фактически не нужен модуль (.c,.cpp) при всех
  • Файл заголовка необходим модулю но включается не один раз, прямо или косвенно.

В моем опыте есть два способа, которые хорошо его обнаруживают:

  • gcc -H или cl.exe/showincludes (решить проблему 2)

    В реальном мире, вы можете экспортировать CFLAGS = -H перед make, если все Makefile не отменяется Варианты CFLAGS. Или, как я использовал, вы может создать оболочку cc/g++ для добавления -H опции принудительно для каждого вызова $ (CC) и $(CXX). и добавьте каталог-оболочка в $PATH переменная, тогда ваш make будет вместо этого использует команду wrapper. из конечно, ваша обложка должна вызывать настоящий gcc-компилятор. Эти трюки необходимо изменить, если ваш Makefile использует gcc напрямую. вместо $(CC) или $ (CXX) или подразумеваемыми правилами.

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

    сделать чистым

    сделать 2 > & 1 | tee result.txt

  • PC-Lint/FlexeLint (проблема с разрешением и 1 и 2)

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

    pclint/flint -vf...

    Это приведет к включению заголовочных файлов pclint, вложенные файлы заголовков будут соответственно отступать.

Ответ 18

Gimpel Software PC Lint может сообщать, когда включенный файл был включен более одного раза в блок компиляции , но он не могут найти файлы, которые не нужны в том виде, который вы ищете.

Изменить: Он может. См. его ответ

Ответ 19

CLion, C/С++ IDE из JetBrains, обнаруживает избыточность, включает в себя готовые к использованию. Они выделены серым цветом в редакторе, но есть функции optimize включает в текущий файл или весь проект.

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