_DEBUG vs NDEBUG

142

Quelle définition de préprocesseur doit être utilisée pour spécifier les sections de débogage du code?

Utilisez #ifdef _DEBUGou #ifndef NDEBUGou existe-t-il une meilleure façon de le faire, par exemple #define MY_DEBUG?

je pense _DEBUG Visual Studio est spécifique, NDEBUG est-il standard?

deft_code
la source

Réponses:

113

Visual Studio définit _DEBUGlorsque vous spécifiez l' option /MTdou /MDd, NDEBUGdésactive les assertions standard-C. Utilisez-les le cas échéant, c'est-à _DEBUG- dire si vous voulez que votre code de débogage soit cohérent avec les techniques de débogage MS CRT et NDEBUGsi vous voulez être cohérent avecassert() .

Si vous définissez vos propres macros de débogage (et que vous ne piratez pas le compilateur ou le runtime C), évitez de commencer les noms par un trait de soulignement, car ils sont réservés.

Christoph
la source
19
+1. NDEBUG en particulier est autorisé à être # non défini et # défini dans une seule TU (et la réinclusion de <assert.h> modifie la macro d'assertion en conséquence). Parce que c'est différent de ce qui est attendu / souhaité, il est courant d'utiliser une autre macro pour contrôler un indicateur de débogage «à l'échelle de la compilation», comme l'indique cette réponse.
1
Apparemment, c'est le compilateur lui-même qui définit ces macros et non Visual Studio (l'IDE). Merci beaucoup pour cette réponse!
Niklas R
NDEBUG n'est pas défini lors de l'utilisation des modèles d'applications de Windows Driver Kit 8.1 également. Dans ce cas, vous devrez peut-être vous fier à _DEBUG.
navossoc
53

NDEBUG est-il standard?

Oui, c'est une macro standard avec la sémantique "Not Debug" pour les standards C89, C99, C ++ 98, C ++ 2003, C ++ 2011, C ++ 2014. Il n'y a pas_DEBUG macros dans les normes.

La norme C ++ 2003 envoie le lecteur à "page 326" à "17.4.2.1 En-têtes" au standard C.

Ce NDEBUG est similaire à celui de la bibliothèque C standard.

En C89 (les programmeurs C appelaient ce standard comme standard C) dans la section "4.2 DIAGNOSTICS", il était dit

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

Si NDEBUG est défini comme un nom de macro au point du fichier source où est inclus, la macro d'assertion est définie simplement comme

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

Si vous regardez la signification des _DEBUGmacros dans Visual Studio https://msdn.microsoft.com/en-us/library/b0084kay.aspx, vous verrez que cette macro est automatiquement définie par votre choix de version de la bibliothèque d'exécution du langage.

Bruziuz
la source
50

Je me fie NDEBUG, car c'est le seul dont le comportement est normalisé entre les compilateurs et les implémentations (voir la documentation pour la macro d'assertion standard). La logique négative est un petit accélérateur de lisibilité, mais c'est un idiome courant auquel vous pouvez vous adapter rapidement.

S'appuyer sur quelque chose comme cela _DEBUGreviendrait à s'appuyer sur un détail d'implémentation d'un compilateur particulier et d'une implémentation de bibliothèque. D'autres compilateurs peuvent ou non choisir la même convention.

La troisième option est de définir votre propre macro pour votre projet, ce qui est tout à fait raisonnable. Le fait d'avoir votre propre macro vous donne la portabilité entre les implémentations et vous permet d'activer ou de désactiver votre code de débogage indépendamment des assertions. Cependant, en général, je déconseille d'avoir différentes classes d'informations de débogage qui sont activées au moment de la compilation, car cela provoque une augmentation du nombre de configurations que vous devez construire (et tester) pour un avantage sans doute minime.

Avec l'une de ces options, si vous utilisez du code tiers dans le cadre de votre projet, vous devez savoir quelle convention il utilise.

Adrian McCarthy
la source
1
#if !defined(NDEBUG)<- @HostileFork n'est-ce pas ce que vous vouliez dire? #ifnon #ifdef?
Bob Stein
1
Commentaire original corrigé via @BobStein: "Quelque chose que j'ai pris de faire pour (légèrement) atténuer la lisibilité" speedbump "est que lorsque vous parlez d'une condition de non-débogage, utilisez #ifdef NDEBUG... mais attirez une attention particulière à la logique négative avec #if !defined(NDEBUG). Sinon, il est un peu difficile d'attraper le n #ifndef NDEBUG"
HostileFork dit ne pas faire confiance à SE
17

La macro NDEBUGcontrôle si les assert()instructions sont actives ou non.

À mon avis, cela est distinct de tout autre débogage - j'utilise donc autre chose que NDEBUGde contrôler les informations de débogage dans le programme. Ce que j'utilise varie en fonction du framework avec lequel je travaille; différents systèmes ont des macros d'activation différentes, et j'utilise ce qui est approprié.

S'il n'y a pas de cadre, j'utiliserais un nom sans trait de soulignement principal; ceux-ci ont tendance à être réservés à «l'implémentation» et j'essaie d'éviter les problèmes de collision de noms - doublement quand le nom est une macro.

Jonathan Leffler
la source
Pouvez-vous expliquer pourquoi vous considérez les assertions comme distinctes des autres types de débogage? Dans quels scénarios voudriez-vous l'un et pas l'autre?
Adrian McCarthy
4
Je garde les assertions actives même lorsque je ne compile pas d'autres fonctionnalités de débogage ou de traçage dans le code. Les affirmations identifient des situations impossibles. Le traçage et le débogage généraux sont totalement séparés par l'OMI.
Jonathan Leffler
2
@AdrianMcCarthy: si vous avez activé TOUS le débogage, cela peut entraîner une exécution INCROYABLEMENT lente des programmes. Il est donc courant de catégoriser les types de débogage et d'autoriser les utilisateurs à les activer / désactiver séparément. MSVC en a deux ou trois qu'ils utilisent pour activer / désactiver divers débogages pour la bibliothèque standard, comme std :: vector.
Mooing Duck
@MooingDuck: D'accord, mais faites la distinction entre «débogage disponible et activé» et «débogage disponible mais désactivé» et «débogage non disponible». La décision disponible / non disponible est un problème de compilation (en code C ou C ++), et l'activation / désactivation est alors une décision d'exécution lorsque le débogage est disponible. Seuls les systèmes de débogage les plus grossiers fonctionnent avec le mode «disponible signifie activé». (Cela dit, le brut peut être efficace, et il existe énormément de systèmes de débogage bruts - mais suffisamment efficaces - dans la nature!)
Jonathan Leffler
2
@MooingDuck: Oui, certains codes de débogage peuvent varier lentement. Dans ce cas, vous souhaiterez peut - être un moyen de contrôler si le code lent s'exécute indépendamment des vérifications triviales. Mais ce n'est pas la même chose que de placer des assertions dans une catégorie et du #ifcode contrôlé dans l'autre. assert(huge_object.IsValid());pourrait être lent alors que ce assert(ptr != nullptr);n'est probablement pas le cas. Je suis d'accord avec Jonathan que la journalisation et le traçage devraient probablement être distincts des assertions, au moins dans les projets plus importants, mais je ne pense pas à la journalisation ou au traçage comme du code de débogage, c'est pourquoi j'ai demandé des éclaircissements.
Adrian McCarthy
6

Soyez cohérent et peu importe lequel. De plus, si pour une raison quelconque vous devez interopérer avec un autre programme ou outil en utilisant un certain identifiant DEBUG, c'est facile à faire

#ifdef THEIRDEBUG
#define MYDEBUG
#endif //and vice-versa
Earlz
la source
4

Malheureusement, il DEBUGest fortement surchargé. Par exemple, il est recommandé de toujours générer et enregistrer un fichier pdb pour les builds RELEASE. Ce qui signifie l'un des -Zxindicateurs et l' -DEBUGoption de l'éditeur de liens. While _DEBUGconcerne les versions de débogage spéciales de la bibliothèque d'exécution, telles que les appels à mallocet free. Puis NDEBUGdésactivera les assertions.

James
la source