2010-02-18 4 views
106

¿Qué preprocesador define debería usarse para especificar secciones de depuración de código?_DEBUG vs NDEBUG

Use #ifdef _DEBUG o #ifndef NDEBUG o existe una forma mejor de hacerlo, p. #define MY_DEBUG?

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

Respuesta

97

Visual Studio define _DEBUG cuando se especifica la opción /MTd o /MDd, NDEBUG desactiva estándar-C afirmaciones. Úselos cuando corresponda, es decir, _DEBUG si desea que su código de depuración sea coherente con MS CRT debugging techniques y NDEBUG si quiere ser coherente con assert().

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

+14

+1. NDEBUG, en particular, se permite # undef'd y # define'd dentro de una sola TU (y la inclusión de cambia la macro de assert en consecuencia). Debido a que esto es diferente de lo esperado/deseado, es común usar otra macro para controlar una bandera de depuración de "compilación" como lo dice esta respuesta. –

+0

Aparentemente, es el compilador el que define estas macros y no Visual Studio (el IDE). Muchas gracias por esta respuesta! –

+0

NDEBUG no está definido 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

6

Sea consistente y no importa cuál. Además, si por alguna razón debe INTEROP con otro programa o herramienta de uso de un determinado identificador de depuración que es fácil de hacer

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

El macro NDEBUG controla si las declaraciones assert() están activas o no.

En mi opinión, eso está separado de cualquier otra depuración, así que uso algo que no sea NDEBUG para 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 marco, usaría un nombre sin un guión bajo inicial; esos tienden a estar reservados a 'la implementación' y trato de evitar problemas con colisiones de nombres, doblemente cuando el nombre es una macro.

+0

¿Puede explicar por qué considera las afirmaciones distintas de otros tipos de depuración? ¿En qué escenarios querrías uno y no el otro? –

+3

Sigo afirmando activo incluso cuando no compilo otras instalaciones de depuración o rastreo en el código. Las afirmaciones identifican situaciones imposibles. El seguimiento y la depuración generales son OMI totalmente independientes de eso. –

+2

@AdrianMcCarthy: si tiene habilitada la depuración ALL, puede hacer que los programas se ejecuten INCREÍBLEMENTE lentamente. Por lo tanto, es común categorizar los tipos de depuración y permitir que las personas los habiliten/deshabiliten por separado. MSVC tiene dos o tres que utilizan para habilitar/deshabilitar varias depuraciones para la biblioteca estándar, como std :: vector. –

33

Confío en NDEBUG, porque es el único cuyo comportamiento está estandarizado en los compiladores y las implementaciones (consulte la documentación para la macro de afirmación estándar). La lógica negativa es una velocidad de lectura reducida, pero es un idioma común al que puedes adaptarte rápidamente.

Para confiar en algo como _DEBUG serí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 ofrece portabilidad en todas las implementaciones y le permite habilitar o deshabilitar su código de depuración independientemente de las aserciones. Aunque, en general, desaconsejo tener diferentes clases de información de depuración que estén habilitadas en tiempo de compilación, ya que causa un aumento en la cantidad de configuraciones que tiene que compilar (y probar) para obtener un beneficio posiblemente pequeño.

Con cualquiera de estas opciones, si utiliza código de terceros como parte de su proyecto, deberá conocer qué convención utiliza.

+3

Algo que he tenido que hacer para (ligeramente) mitigar la legibilidad "speedbump" es que cuando se habla de una condición sin eliminación de errores use '#ifdef NDEBUG' ... pero luego llame la atención especialmente a la lógica negativa con' #ifdef ! defined (NDEBUG) '. De lo contrario, es un poco difícil atrapar la 'n' en' #ifndef NDEBUG'. – HostileFork

3

Desafortunadamente "DEBUG" está sobrecargado. Por ejemplo, se recomienda siempre generar y guardar un archivo pdb para versiones RELEASE. Lo que significa una de las opciones -Zx flags, y -DEBUG linker. Mientras que _DEBUG se relaciona con versiones especiales de depuración de la biblioteca en tiempo de ejecución, como llamadas a malloc y gratuitas. Entonces NDEBUG desactivará las aserciones.

25

¿Es NDEBUG estándar?

Sí, es una macro estándar con la semántica "No se depura" para las normas C89, C99, C++ 98, C++ 2003, C++ 2011, C++ 2014. No hay macros _DEBUG en los estándares.

C++ estándar 2003 envía al lector a "página 326" a "17.4.2.1" encabezados la norma C.

Eso NDEBUG es similar ya que es la misma que la biblioteca C estándar.

En C89 (programadores de C llamaron a este estándar como C estándar) en el apartado "4.2 DIAGNOSTICS" se dijo

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

Si NDEBUG se define como un nombre de macro en el punto en el archivo de origen donde se incluye, la macro assert se define simplemente como

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

Si mira el significado de las macros _DEBUG en Visual Studio https://msdn.microsoft.com/en-us/library/b0084kay.aspx , entonces se verá que esta macro se define automáticamente por la versión de la biblioteca del tiempo de ejecución del idioma.

Cuestiones relacionadas