Ответы:
Visual Studio определяет, _DEBUG
когда вы указываете опцию /MTd
или /MDd
, NDEBUG
отключает утверждения стандартного Си. Используйте их по мере необходимости, т. Е. _DEBUG
Если вы хотите, чтобы ваш код отладки соответствовал методам отладки MS CRT, и NDEBUG
если вы хотите, чтобы они были совместимы assert()
.
Если вы определяете свои собственные отладочные макросы (и вы не взламываете компилятор или среду выполнения C), избегайте начинать имена с подчеркивания, поскольку они зарезервированы.
Является ли стандарт NDEBUG?
Да, это стандартный макрос с семантикой «Не отлаживать» для стандартов C89, C99, C ++ 98, C ++ 2003, C ++ 2011, C ++ 2014. В стандартах нет _DEBUG
макросов.
Стандарт C ++ 2003 отправляет читателю на «странице 326» в «17.4.2.1 заголовки» к стандарту C.
Этот NDEBUG похож на Это так же, как стандартная библиотека C.
В C89 (программисты на C назвали этот стандарт стандартом C) в разделе «4.2 ДИАГНОСТИКА» было сказано
http://port70.net/~nsz/c/c89/c89-draft.html
Если NDEBUG определен как имя макроса в той точке исходного файла, в которую он включен, макрос assert определяется просто как
#define assert(ignore) ((void)0)
Если вы посмотрите на значение _DEBUG
макросов в Visual Studio
https://msdn.microsoft.com/en-us/library/b0084kay.aspx,
то увидите, что этот макрос автоматически определяется вашим выбором языковой версии библиотеки времени выполнения.
Я полагаюсь NDEBUG
, потому что это единственный, чье поведение стандартизировано по компиляторам и реализациям (см. Документацию для стандартного макроса assert). Негативная логика - это небольшая скорость чтения, но это обычная идиома, к которой можно быстро адаптироваться.
Полагаться на что-то вроде _DEBUG
- значит полагаться на детали реализации конкретного компилятора и реализации библиотеки. Другие компиляторы могут или не могут выбрать то же соглашение.
Третий вариант - определить собственный макрос для вашего проекта, что вполне разумно. Наличие собственного макроса обеспечивает переносимость между реализациями и позволяет включать или отключать код отладки независимо от утверждений. Хотя, в общем, я не советую иметь разные классы отладочной информации, которые включаются во время компиляции, так как это приводит к увеличению количества конфигураций, которые вы должны построить (и протестировать) для, возможно, небольшой выгоды.
При использовании любого из этих вариантов, если вы используете сторонний код в качестве части своего проекта, вы должны знать, какое соглашение оно использует.
#if !defined(NDEBUG)
<- @HostileFork - это не то, что вы имели в виду? #if
нет #ifdef
?
#ifdef NDEBUG
... но затем обратим особое внимание на отрицательную логику с помощью #if !defined(NDEBUG)
. В противном случае это немного трудно поймать в #ifndef NDEBUG
"
Макрос NDEBUG
контролирует, assert()
являются ли операторы активными или нет.
На мой взгляд, это отдельно от любой другой отладки - поэтому я использую что-то кроме NDEBUG
контроля информации отладки в программе. То, что я использую, варьируется в зависимости от структуры, с которой я работаю; разные системы имеют разные разрешающие макросы, и я использую то, что подходит.
Если рамки отсутствуют, я бы использовал имя без начального подчеркивания; они, как правило, зарезервированы для «реализации», и я стараюсь избегать проблем с конфликтами имен - вдвойне, когда имя является макросом.
#if
управляемый код в другую. assert(huge_object.IsValid());
может быть медленным, а assert(ptr != nullptr);
может и нет. Я согласен с Джонатаном в том, что ведение журнала и трассировка должны, вероятно, отличаться от утверждений, по крайней мере, в более крупных проектах, но я не думаю о ведении журнала или трассировке как отладочном коде, поэтому я попросил разъяснений.
К сожалению DEBUG
сильно перегружен. Например, рекомендуется всегда генерировать и сохранять файл pdb для сборок RELEASE. Что означает один из -Zx
флагов и -DEBUG
вариант компоновщика. Хотя _DEBUG
относится к специальным отладочным версиям библиотеки времени выполнения, таким как вызовы malloc
и free
. Тогда NDEBUG
отключим утверждения.