_DEBUG проти NDEBUG


142

Яке визначення препроцесора слід використовувати для вказівки розділів налагодження коду?

Використовуйте #ifdef _DEBUGабо #ifndef NDEBUGє кращий спосіб зробити це, наприклад #define MY_DEBUG?

Я думаю _DEBUG, що Visual Studio є специфічним, стандарт NDEBUG?

Відповіді:


113

Visual Studio визначає, _DEBUGколи ви вказуєте параметр /MTdабо /MDdпараметр, NDEBUGвідключає стандартні твердження C. Використовуйте їх, коли це доречно, тобто _DEBUGякщо ви хочете, щоб ваш код налагодження відповідав методикам налагодження MS CRT і NDEBUGякщо ви хочете відповідати assert().

Якщо ви визначаєте свої власні макроси налагодження (і ви не зламаєте компілятор або C виконання), уникайте запуску імен із підкресленням, оскільки вони зарезервовані.


19
+1. Зокрема, NDEBUG може бути # undef'd і # define'd в межах одного TU (і повторне включення <assert.h> відповідно змінює макрос assrt). Оскільки це відрізняється від очікуваного / бажаного, звичайно використовувати інший макрос для управління прапором налагодження "на всі компіляції", як зазначено в цій відповіді.

1
Мабуть, саме цей компілятор визначає ці макроси, а не Visual Studio (IDE). Дякую за цю відповідь!
Niklas R

NDEBUG не визначений і при використанні шаблонів додатків з Windows Driver Kit 8.1. У цьому випадку вам може знадобитися покластися на _DEBUG.
navossoc

53

Чи стандарт NDEBUG?

Так, це стандартний макрос із семантичним "Not Debug" для стандартів C89, C99, C ++ 98, C ++ 2003, C ++ 2011, C ++ 2014. У _DEBUGстандартах немає макросів.

Стандарт C ++ 2003 надсилає зчитувач на "сторінку 326" на "17.4.2.1 заголовки" до стандарту C.

Цей NDEBUG подібний, оскільки це те саме, що і бібліотека Standard C.

У C89 (програмісти C назвали цей стандарт як стандарт С) у розділі "4.2 ДІАГНОСТИКА" було сказано

http://port70.net/~nsz/c/c89/c89-draft.html

Якщо NDEBUG визначений як ім'я макросу в точці вихідного файлу, куди він включений, макрос затвердження визначається просто як

     #define assert(ignore) ((void)0)

Якщо подивитися на значення _DEBUGмакросів у Visual Studio https://msdn.microsoft.com/en-us/library/b0084kay.aspx, то буде видно, що цей макрос автоматично визначається вашим вибором бібліотечної версії бібліотеки часу виконання.


50

Я покладаюсь на це NDEBUG, тому що це єдиний, поведінка якого стандартизовано серед компіляторів та реалізацій (див. Документацію до стандартного макросу assrt). Негативна логіка - це невелика швидкість зчитування, але це загальна ідіома, до якої можна швидко адаптуватися.

Покладатися на щось подібне _DEBUGбуло б покладатися на деталі реалізації певного компілятора та реалізації бібліотеки. Інші компілятори можуть або не можуть обрати ту саму умову.

Третій варіант - визначити власний макрос для свого проекту, що цілком розумно. Наявність власного макросу дає вам портативність у різних реалізаціях, і це дозволяє ввімкнути або відключити код налагодження незалежно від тверджень. Хоча, загалом, я раджу не мати різних класів налагоджувальної інформації, які увімкнено під час компіляції, оскільки це призводить до збільшення кількості конфігурацій, які ви повинні створити (і протестувати) для, мабуть, невеликої вигоди.

З будь-яким із цих варіантів, якщо ви використовуєте код сторони як частину свого проекту, вам доведеться знати, яку конвенцію він використовує.


1
#if !defined(NDEBUG)<- @HostileFork це не те, що ти мав на увазі? #ifні #ifdef?
Боб Штейн

1
Оригінальний коментар, виправлений через @BobStein: "Щось я взяв на себе, щоб (трохи) пом'якшити читабельність" speedbump ", це те, що, коли йдеться про умову без налагодження, використовуйте #ifdef NDEBUG... але потім зверніть особливу увагу на негативну логіку #if !defined(NDEBUG). Інакше трохи важко впіймати російське #ifndef NDEBUG"
HostileFork каже, що не довіряйте SE

17

Макрос NDEBUGкерує тим, чи assert()оператори активні, чи ні.

На мій погляд, це є окремим від будь-якої іншої налагодження - тому я використовую щось інше, ніж NDEBUGдля контролю інформації про налагодження в програмі. Те, що я використовую, залежить від основи, з якою я працюю; різні системи мають різні макроси, що дозволяють, і я використовую все, що підходить.

Якщо немає рамки, я б використовував ім'я без провідного підкреслення; вони, як правило, зарезервовані до "реалізації", і я намагаюся уникати проблем зі зіткненнями імен - вдвічі, коли ім'я є макросом.


Чи можете ви пояснити, чому ви вважаєте твердження відмінними від інших типів налагодження? У яких сценаріях ви хотіли б одного, а не іншого?
Адріан Маккарті

4
Я продовжую активні твердження, навіть коли я не збираю інші засоби налагодження чи відстеження в код. Твердження визначають неможливі ситуації. Загальне відстеження та налагодження є IMO повністю відокремленим від цього.
Джонатан Леффлер

2
@AdrianMcCarthy: якщо увімкнено ВСІ налагодження, це може призвести до того, що програми НЕВІДКЛЮЧНО запускаються. Тож звичайно класифікувати типи налагодження та дозволяти людям включати / вимикати їх окремо. MSVC має два або три, які вони використовують для вмикання / відключення різних налагоджень для стандартної бібліотеки, наприклад std :: vector.
Mooing Duck

@MooingDuck: Погоджено, але розрізняти "налагодження доступно та увімкнено" та "налагодження доступно, але вимкнено" та "налагодження не доступне". Доступне / недоступне рішення - це питання про час компіляції (в коді C або C ++), і увімкнено / вимкнено потім рішення часу виконання, коли налагодження доступне. Тільки найкрутіші системи налагодження працюють у режимі "доступні засоби". (Сказано, що сировина може бути ефективною, і є дуже багато сирого - але досить ефективного - налагодження систем там у дикій природі!)
Джонатан Леффлер

2
@MooingDuck: Так, деякий код налагодження може змінюватися повільно. У цьому випадку вам може знадобитися спосіб контролювати те, чи працює повільний код незалежно від тривіальних перевірок. Але це не те саме, що ставити твердження в одну категорію і #if-контрольований код в іншій. assert(huge_object.IsValid());може бути повільним, assert(ptr != nullptr);напевно, ні. Я погоджуюсь з Джонатаном, що реєстрація та відстеження, ймовірно, повинні відрізнятися від тверджень, принаймні, у більших проектах, але я не думаю, що реєстрація чи відстеження є кодом налагодження, тому я попросив роз'яснити.
Адріан Маккарті

6

Будьте послідовними і не важливо, який саме. Крім того, якщо з якоїсь причини ви повинні взаємодіяти з іншою програмою чи інструментом, використовуючи певний ідентифікатор DEBUG, це легко зробити

#ifdef THEIRDEBUG
#define MYDEBUG
#endif //and vice-versa

4

На жаль DEBUG, сильно перевантажений. Наприклад, рекомендується завжди генерувати та зберігати pdb-файл для RELEASE-збірок. Що означає один із -Zxпрапорів і -DEBUGпараметр linker. Хоча _DEBUGстосується спеціальних версій налагодження бібліотеки виконання, таких як дзвінки до mallocта free. Потім NDEBUGбуде відключено твердження.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.