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

Примечание. Это расширение более раннего вопроса, который я задал здесь: /">Увеличивают ли дополнительные определения функций/методов занимаемую программой память?

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

Я задаю этот вопрос как с точки зрения C++, так и с точки зрения Java. Я использую Code::Blocks и Eclipse в качестве IDE, если это как-то влияет на ответ.


person Lewis    schedule 23.12.2010    source источник


Ответы (5)


С точки зрения Java существует множество стратегий:

  • Если сообщения журнала создаются фрагментами кода, используйте log4j или одну из других сред ведения журнала.

  • Если это полный метод, который не используется в производственном коде, оставьте его там. Во время выполнения компилятор JIT заметит, что он не используется, и не будет его компилировать. Код может все еще быть там во время выполнения (в виде нескомпилированных байт-кодов), но влияние на объем памяти будет незначительным... учитывая, что JVM требуется несколько мегабайт пространства в куче только для того, чтобы начать работу.

  • Если это класс или набор классов (например, тестовые классы JUnit), поместите его/их в параллельный пакет с «тестом» где-нибудь в имени пакета и отфильтруйте его/их при создании файла JAR.

  • Если вы используете Maven, поместите тестовые классы в каталог «src/test/java», а не в «src/main/java», и команда maven автоматически их исключит.

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

person Stephen C    schedule 24.12.2010
comment
Обратите внимание, что ответ автора является правильным для аспекта C ++ этого вопроса, я просто не могу отметить его правильно. - person Lewis; 24.12.2010

Для С++ вы можете использовать макросы препроцессора:

#ifnef NDEBUG
void dbgFunction() { ... }
#endif

NDEBUG — это стандартный макрос, используемый assert: ваши assertion не будут оцениваться, если установлен NDEBUG.


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

person peoro    schedule 23.12.2010
comment
Этот ответ также полностью правильный, но я, к сожалению, не могу отметить два ответа как правильные. - person Lewis; 24.12.2010
comment
Но если вы просто помещаете отладочный код в операторы assert, то в этом нет необходимости. Наличие объектов, которые меняют характеристики между сборками выпуска/отладки, не является хорошей идеей. Сохраните функцию, просто убедитесь, что код вызывается только из утверждений. - person Martin York; 24.12.2010
comment
Итак, если методы отладки вызываются только из утверждений утверждений, они будут оптимизированы компилятором при выполнении сборки выпуска? - person Lewis; 24.12.2010
comment
Только вызов ваших функций отладки. Функции останутся в вашем двоичном файле, хотя они никогда не будут вызываться. - person peoro; 24.12.2010

Чтобы добавить к ответу peoro на C ++, в ваших проектах выпуска всегда должен быть определен NDEBUG, а в ваших проектах отладки всегда должен быть определен _DEBUG, чтобы вы могли протестировать любой из них или создать свои собственные директивы препроцессора для исключения кода.

Лично я считаю очень полезным время от времени иметь несколько моих собственных директив препроцессора, и отличное место для их размещения — в stdafx.h, если вы используете предварительно скомпилированные заголовочные файлы. Вы можете включить или отключить целые функции или части кода, которые могут быть в процессе разработки или просто нежелательны для определенных сборок. Например, в одном приложении, изменив один дефайн, я могу переключиться с OpenGl на DirectX или полностью исключить 3D-рендеринг из проекта.

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

person AJG85    schedule 24.12.2010

Используйте переключатели препроцессора

#ifdef MY_DEBUG_SWITCH
// debug code goes here
#endif
person watson1180    schedule 23.12.2010

В мире Java вы можете использовать log4j для всех ваших целей ведения журнала, имея журнал отладки в своем кодируйте как log.debug(). В вашем производственном коде вы можете запустить код с уровнем свойства log4j в любом месте выше DEBUG, например INFO. Вы можете получить более подробную информацию здесь.

person dimitrisli    schedule 23.12.2010
comment
ОП спрашивал, как удалить его функции, чтобы уменьшить объем памяти его программы. Ваше решение немного ускорит работу и удалит эффекты функций log4j, но не уменьшит объем памяти и оставит небольшие накладные расходы из-за вызова функций log4j (которые будут проверять уровень отладки, сбой). - person peoro; 24.12.2010