Как я должен обнаружить ненужные #include файлы в большом проекте C++?

Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException вообще.

См. также: A хороший список лучших практик

Я бы добавил, очень важно, хорошо использовать модификатор final. Использование "окончательной" модификатор, когда это применимо в Java

Сводка:

  1. Используйте модификатор final для обеспечения хорошей инициализации.
  2. Избегайте возврата null в методы, например, при возврате пустых коллекций.
  3. Использовать аннотации @NotNull и @Nullable
  4. Быстрое завершение работы и использование утверждений, чтобы избежать распространения нулевых объектов через все приложение, когда они не должен быть пустым.
  5. Сначала используйте значения с известным объектом: if("knownObject".equals(unknownObject)
  6. Предпочитают valueOf() поверх toString ().
  7. Используйте null safe StringUtils StringUtils.isEmpty(null).

95
задан LogicStuff 22 December 2015 в 22:48
поделиться

16 ответов

В то время как это не покажет ненужный, включают файлы, Visual Studio имеет установку /showIncludes (щелчок правой кнопкой по .cpp файл, Properties->C/C++->Advanced), который произведет дерево всех включенных файлов во время компиляции. Это может помочь в идентификации файлов, которые не должны должны быть быть включены.

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

49
ответ дан LogicStuff 24 November 2019 в 05:50
поделиться

Некоторые существующие ответы указывают, что это твердо. Это действительно верно, потому что Вам нужен полный компилятор для обнаружения случаев, в которых предописание было бы соответствующим. Вы наклоняете C++ синтаксического анализа, не зная то, что означают символы; грамматика просто слишком неоднозначна для этого. Необходимо знать, называет ли определенное имя класс (мог бы быть вперед - объявлен), или переменная (не может). Кроме того, необходимо быть осведомлены о пространстве имен.

0
ответ дан MSalters 24 November 2019 в 05:50
поделиться

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

#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN

См. http://support.microsoft.com/kb/166474

1
ответ дан Roger Nelson 24 November 2019 в 05:50
поделиться

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

http://msdn.microsoft.com/en-us/library/szfdksca (По сравнению с 71) .aspx

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

1
ответ дан anon6439 24 November 2019 в 05:50
поделиться

Если Вы надеетесь удалять ненужный #include файлы для уменьшения времени изготовления, время и деньги могли бы быть лучше проведены, параллелизируя процесс сборки с помощью , cl.exe / MP , делают-j, Xoreax IncrediBuild, distcc / мороженое , и т.д.

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

2
ответ дан bk1e 24 November 2019 в 05:50
поделиться

Линт ПК может действительно сделать это. Один простой способ сделать это должно настроить, он для обнаружения просто неиспользованный включает файлы и игнорирует все другие проблемы. Это довольно просто - чтобы включить просто сообщение 766 ("Заголовочный файл, не используемый в модуле"), просто включать опции-w0 +e766 в командную строку.

тот же подход может также использоваться с похожими сообщениями такой как 964 ("Заголовочный файл, не непосредственно используемый в модуле") и 966 ("Косвенно включенный заголовочный файл, не используемый в модуле").

FWIW я записал об этом более подробно в сообщении в блоге на прошлой неделе в http://www.riverblade.co.uk/blog.php?archive=2008_09_01_archive.xml#3575027665614976318 .

3
ответ дан 24 November 2019 в 05:50
поделиться

Если Вы интересуетесь этой темой в целом, Вы могли бы хотеть проверить Lakos Крупномасштабная Разработка программного обеспечения C++ . Это немного датировано, но входит в большой "физический дизайн" проблемы как нахождение абсолютного минимума заголовков, которые должны быть включены. Я действительно не видел этот вид вещи, обсужденной больше нигде.

5
ответ дан Adrian 24 November 2019 в 05:50
поделиться

Запустите с каждого, включают файл и гарантируют, чтобы каждый включал файл, только включает то, что необходимо для компиляции себя. Любой включает файлы, которые тогда отсутствуют для файлов C++, может быть добавлен к самим файлам C++.

Для каждого включают и исходный файл, комментируют, каждый включает файл по одному и видит, компилирует ли это.

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

2
ответ дан selwyn 24 November 2019 в 05:50
поделиться

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

Говорят, что Ваш исходный файл включает a.h и b.h; a.h содержит #define USE_FEATURE_X и использование b.h #ifdef USE_FEATURE_X. Если #include "a.h" комментируется, Ваш файл может все еще скомпилировать, но не может сделать то, что Вы ожидаете. Обнаружение этого программно нетривиально.

Независимо от того, что инструмент делает это должно было бы знать Вашу среду сборки также. Если a.h похож:

#if defined( WINNT )
   #define USE_FEATURE_X
#endif

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

10
ответ дан Graeme Perrow 24 November 2019 в 05:50
поделиться

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

<час>

кажется, что теперь у Eric Raymond есть инструмент для этого .

Google cpplint.py имеет, "включают то, что Вы используете" правило (среди многих других), но насколько я могу сказать, нет "включают [только 115], что Вы используете". Несмотря на это, это может быть полезно.

9
ответ дан Max Lybbert 24 November 2019 в 05:50
поделиться

Линт пк работы вполне хорошо для этого, и это находит все виды других глупых проблем для Вас также. Это имеет параметры командной строки, которые могут использоваться для создания Внешних Инструментов в Visual Studio, но я нашел, что Визуальный Линт дополнение легче работать с. Даже бесплатная версия Визуального Линта помогает. Но дайте Линту ПК выстрел. При конфигурировании его так, который это не дает Вам, слишком много предупреждений занимают немного времени, но Вы будете поражены тем, что это поднимает.

30
ответ дан Joe 24 November 2019 в 05:50
поделиться

!!Отказ от ответственности!! Я работаю над коммерческим инструментом статического анализа (не Линт ПК).!!Отказ от ответственности!!

существует несколько проблем с простым не подход парсинга:

1) Наборы Перегрузки:

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

2) Шаблонные специализации:

Подобный примеру перегрузки, если у Вас есть частичные или явные специализации для шаблона, Вы хотите, чтобы они все были видимы, когда шаблон используется. Могло бы случиться так, что специализации для основного шаблона находятся в различных заголовочных файлах. Удаление заголовка со специализацией не вызовет ошибку компиляции, но может привести к неопределенному поведению, если та специализация была бы выбрана. (См.: Видимость шаблонной специализации функции C++ )

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

26
ответ дан Community 24 November 2019 в 05:50
поделиться

Если Ваши заголовочные файлы обычно запускаются с

#ifndef __SOMEHEADER_H__
#define __SOMEHEADER_H__
// header contents
#endif

(в противоположность использованию #pragma однажды), Вы могли изменить это на:

#ifndef __SOMEHEADER_H__
#define __SOMEHEADER_H__
// header contents
#else 
#pragma message("Someheader.h superfluously included")
#endif

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

3
ответ дан Sam 24 November 2019 в 05:50
поделиться

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

4
ответ дан 24 November 2019 в 05:50
поделиться

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

4
ответ дан 24 November 2019 в 05:50
поделиться

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

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

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

0
ответ дан 24 November 2019 в 05:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: