169 votes

_DEBUG vs NDEBUG

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

Utilisez #ifdef _DEBUG o #ifndef NDEBUG ou existe-t-il un meilleur moyen de le faire, par ex. #define MY_DEBUG ?

Je pense _DEBUG est spécifique à Visual Studio, NDEBUG est standard ?

137voto

Christoph Points 64389

Visual Studio définit _DEBUG lorsque vous spécifiez l'option /MTd o /MDd option, NDEBUG désactive les assertions standard-C. Utilisez-les lorsque cela est approprié, c'est-à-dire _DEBUG si vous voulez que votre code de débogage soit cohérent avec le Techniques de débogage du MS CRT y NDEBUG si vous voulez être cohérent avec assert() .

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

23 votes

+1. NDEBUG en particulier est autorisé à être #undef'd et #define'd dans une même TU (et la réinclusion de <assert.h> modifie la macro assert en conséquence). Parce que cela est différent de ce qui est attendu/souhaité, il est courant d'utiliser une autre macro pour contrôler un drapeau de débogage "compile-wide" comme le dit cette réponse.

2 votes

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 !

0 votes

NDEBUG n'est pas défini lorsque vous utilisez également des modèles d'applications du Windows Driver Kit 8.1. Dans ce cas, vous devrez peut-être vous fier à _DEBUG.

57voto

Adrian McCarthy Points 17018

Je compte sur NDEBUG car c'est la seule dont le comportement est normalisé entre les compilateurs et les implémentations (voir la documentation de la macro assert standard). La logique négative est un petit obstacle à la lisibilité, mais c'est un idiome commun auquel vous pouvez vous adapter rapidement.

Se fier à quelque chose comme _DEBUG serait de s'appuyer sur un détail d'implémentation d'un compilateur et d'une bibliothèque particuliers. D'autres compilateurs peuvent choisir ou non la même convention.

La troisième option consiste à définir votre propre macro pour votre projet, ce qui est tout à fait raisonnable. Avoir votre propre macro vous donne une 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 entraîne une augmentation du nombre de configurations que vous devez construire (et tester) pour un bénéfice relativement faible.

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

1 votes

#if !defined(NDEBUG) <-- @HostileFork n'est-ce pas ce que vous vouliez dire ? #if no #ifdef ?

1 votes

Commentaire original corrigé par @BobStein : "J'ai pris l'habitude de faire quelque chose pour atténuer (légèrement) le "ralentisseur" de la lisibilité : lorsque l'on parle d'une condition de non-débogage, il faut utiliser #ifdef NDEBUG ...mais ensuite attirer une attention particulière sur la logique négative avec #if !defined(NDEBUG) . Sinon, c'est un peu difficile d'attraper le n en #ifndef NDEBUG "

25voto

Jonathan Leffler Points 299946

La macro NDEBUG contrôle si assert() Les déclarations sont actives ou non.

À mon avis, cela est séparé de tout autre débogage - j'utilise donc autre chose que NDEBUG pour contrôler les informations de débogage dans le programme. Ce que j'utilise varie en fonction de l'environnement avec lequel je travaille ; les 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 framework, j'utiliserais un nom sans trait de soulignement en tête ; ceux-ci ont tendance à être réservés à "l'implémentation" et j'essaie d'éviter les problèmes de collision de noms - d'autant plus lorsque le nom est une macro.

1 votes

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 ?

5 votes

Je garde les assertions actives même si je ne compile pas d'autres moyens de débogage ou de traçage dans le code. Les assertions identifient les situations impossibles. Le traçage et le débogage général sont, selon l'OMI, totalement distincts de cela.

3 votes

@AdrianMcCarthy : si vous avez TOUTES les fonctions de débogage activées, les programmes peuvent s'exécuter INCROYABLEMENT lentement. Il est donc courant de catégoriser les types de débogage et de permettre aux gens de 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.

8voto

Earlz Points 19355

Soyez cohérent et peu importe lequel. De plus, si pour une raison quelconque, vous devez interagir avec un autre programme ou un outil utilisant un certain identifiant DEBUG, il est facile de le faire.

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

5voto

James Points 21

Malheureusement DEBUG est fortement surchargé. Par exemple, il est recommandé de toujours générer et sauvegarder un fichier pdb pour les builds RELEASE. Ce qui signifie que l'un des -Zx et -DEBUG option de liaison. Alors que _DEBUG concerne les versions de débogage spéciales de la bibliothèque d'exécution, comme les appels à malloc y free . Ensuite, NDEBUG désactivera les assertions.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X