_DEBUG vs NDEBUG

142

¿Qué definición de preprocesador se debe usar para especificar secciones de código de depuración?

Use #ifdef _DEBUGo #ifndef NDEBUGo ¿hay una mejor manera de hacerlo, por ejemplo #define MY_DEBUG?

Creo que _DEBUGes específico de Visual Studio, ¿es NDEBUG estándar?

código_deft
fuente

Respuestas:

113

Visual Studio define _DEBUGcuando especifica la opción /MTdo /MDd, NDEBUGdeshabilita las aserciones estándar-C. Úselos cuando sea apropiado, es decir, _DEBUGsi desea que su código de depuración sea coherente con las técnicas de depuración de MS CRT y NDEBUGsi lo desea assert().

Si define sus propias macros de depuración (y no piratea el compilador o el tiempo de ejecución de C), evite comenzar los nombres con un guión bajo, ya que están reservados.

Christoph
fuente
19
+1. NDEBUG, en particular, puede ser # undef'd y # define'd dentro de una única TU (y al incluir <afirmar.h> cambia la macro de aserción en consecuencia). Como esto es diferente de lo esperado / deseado, es común usar otra macro para controlar un indicador de depuración "en toda la compilación" como dice esta respuesta.
1
Aparentemente, es el compilador mismo el que define estas macros y no Visual Studio (el IDE). Muchas gracias por esta respuesta!
Niklas R
NDEBUG no se define cuando se usan plantillas de aplicaciones del Kit de controladores de Windows 8.1 también. En este caso, es posible que deba confiar en _DEBUG.
navossoc
53

¿Es estándar NDEBUG?

Sí, es una macro estándar con la semántica "No depurar" para los estándares C89, C99, C ++ 98, C ++ 2003, C ++ 2011, C ++ 2014. No hay _DEBUGmacros en los estándares.

El estándar C ++ 2003 envía al lector en la "página 326" en "17.4.2.1 Encabezados" al estándar C.

Ese NDEBUG es similar a Esto es lo mismo que la biblioteca Estándar C.

En C89 (los programadores de C llamaron a este estándar como estándar C) en la sección "4.2 DIAGNÓSTICO" se dijo

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

Si NDEBUG se define como un nombre de macro en el punto del archivo fuente donde se incluye, la macro de aserción se define simplemente como

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

Si observa el significado de las _DEBUGmacros en Visual Studio https://msdn.microsoft.com/en-us/library/b0084kay.aspx , se verá que esta macro se define automáticamente por su elección de versión de biblioteca de tiempo de ejecución de idioma.

bruziuz
fuente
50

Confío en NDEBUGque es el único cuyo comportamiento está estandarizado en compiladores e implementaciones (consulte la documentación para la macro de aserción estándar). La lógica negativa es un pequeño salto de velocidad de legibilidad, pero es un idioma común al que puede adaptarse rápidamente.

Confiar en algo así _DEBUGsería confiar en un detalle de implementación de un compilador particular y la implementación de la biblioteca. Otros compiladores pueden o no elegir la misma convención.

La tercera opción es definir su propia macro para su proyecto, lo cual es bastante razonable. Tener su propia macro le brinda portabilidad entre las implementaciones y le permite habilitar o deshabilitar su código de depuración independientemente de las afirmaciones. Aunque, en general, desaconsejo tener diferentes clases de información de depuración que estén habilitadas en el momento de la compilación, ya que causa un aumento en el número de configuraciones que tiene que construir (y probar) para obtener un beneficio posiblemente pequeño.

Con cualquiera de estas opciones, si usa código de terceros como parte de su proyecto, tendrá que saber qué convención usa.

Adrian McCarthy
fuente
1
#if !defined(NDEBUG)<- @HostileFork ¿no es eso lo que querías decir? #ifno #ifdef?
Bob Stein el
1
Comentario original corregido a través de @BobStein: "Algo que he hecho para mitigar (ligeramente) la legibilidad" speedbump "es que cuando se habla de un uso sin condiciones de depuración #ifdef NDEBUG... pero luego preste especial atención a la lógica negativa con #if !defined(NDEBUG). De lo contrario, es un poco difícil atrapar la n #ifndef NDEBUG"
HostileFork dice que no confíes en SE
17

La macro NDEBUGcontrola si las assert()declaraciones están activas o no.

En mi opinión, eso está separado de cualquier otra depuración, por lo que uso algo más que NDEBUGpara controlar la información de depuración en el programa. Lo que uso varía, dependiendo del marco con el que estoy trabajando; diferentes sistemas tienen diferentes macros habilitadoras, y yo uso lo que sea apropiado.

Si no hay un marco, usaría un nombre sin un guión bajo; esos tienden a estar reservados para 'la implementación' y trato de evitar problemas con las colisiones de nombres, doblemente cuando el nombre es una macro.

Jonathan Leffler
fuente
¿Puede explicar por qué considera las afirmaciones distintas de otros tipos de depuración? ¿En qué escenarios querrías uno y no el otro?
Adrian McCarthy
44
Mantengo las afirmaciones activas incluso cuando no compilo otras instalaciones de depuración o rastreo en el código. Las afirmaciones identifican situaciones imposibles. El rastreo general y la depuración están totalmente separados de la OMI.
Jonathan Leffler
2
@AdrianMcCarthy: si tiene TODA la depuración habilitada, puede hacer que los programas se ejecuten INCREÍBLEMENTE lentamente. Por lo tanto, es común clasificar los tipos de depuración y permitir que las personas los habiliten / deshabiliten por separado. MSVC tiene dos o tres que usan para habilitar / deshabilitar varias depuraciones para la biblioteca estándar, como std :: vector.
Mooing Duck
@MooingDuck: De acuerdo, pero distingue entre 'depuración disponible y habilitada' y 'depuración disponible pero deshabilitada' y 'depuración no disponible'. La decisión disponible / no disponible es un problema de tiempo de compilación (en código C o C ++), y la habilitación / deshabilitación es una decisión de tiempo de ejecución cuando la depuración está disponible. Solo los sistemas de depuración más crudos funcionan con el modo 'medios disponibles habilitados'. (Dicho esto, el crudo puede ser efectivo, y hay una gran cantidad de crudo, pero lo suficientemente efectivo, ¡sistemas de depuración en la naturaleza!)
Jonathan Leffler
2
@MooingDuck: Sí, algunos códigos de depuración pueden variar lentamente. En ese caso, es posible que desee una forma de controlar si el código lento se ejecuta independientemente de las comprobaciones triviales. Pero eso no es lo mismo que poner aserciones en una categoría y #ifcódigo controlado en la otra. assert(huge_object.IsValid());podría ser lento mientras que assert(ptr != nullptr);probablemente no lo sea. Estoy de acuerdo con Jonathan en que el registro y el seguimiento probablemente deberían ser distintos de las afirmaciones, al menos en proyectos más grandes, pero no pienso en el registro o el seguimiento como código de depuración, por lo que solicité una aclaración.
Adrian McCarthy
6

Sea consistente y no importa cuál. Además, si por algún motivo debe interoperar con otro programa o herramienta utilizando un determinado identificador de DEPURACIÓN, es fácil hacerlo

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

Lamentablemente DEBUGestá sobrecargado. Por ejemplo, se recomienda generar y guardar siempre un archivo pdb para las versiones RELEASE. Lo que significa una de las -Zxbanderas y la -DEBUGopción de enlazador. Mientras se _DEBUGrelaciona con versiones especiales de depuración de la biblioteca en tiempo de ejecución, como llamadas a mallocy free. Luego NDEBUGdeshabilitará las aserciones.

James
fuente