Ответы:
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отключим утверждения.