Pregunta

Con eso quiero decir, ¿qué debo hacer para tener aserciones útiles en mi código?

MFC es bastante fácil, solo uso ASSERT (algo).

¿Cuál es la forma que no es MFC?

Editar: ¿Es posible detener la ruptura de aserciones en afirmar.c en lugar de en mi archivo que llamó aserción ()?

Editar: ¿Cuál es la diferencia entre <assert.h> & amp; <cassert>?

Respuesta aceptada: Muchas respuestas excelentes en esta publicación, me gustaría poder aceptar más de una respuesta (o alguien las combinaría todas). Entonces la respuesta se otorga a Ferruccio (por la primera respuesta).

¿Fue útil?

Solución

#include <cassert>

assert(something);

y para la verificación en tiempo de compilación, las afirmaciones estáticas de Boost son bastante útiles:

#include <boost/static_assert.hpp>

BOOST_STATIC_ASSERT(sizeof(int) == 4);  // compile fails if ints aren't 32-bit

Otros consejos

Depende de si está buscando algo que funcione fuera de Visual C ++. También depende del tipo de afirmación que esté buscando.

Hay algunos tipos de afirmaciones:

  1. Preprocesador
    Estas afirmaciones se realizan utilizando la directiva de preprocesador #error
    Las afirmaciones del preprocesador solo se evalúan durante la fase de preprocesamiento y, por lo tanto, no son útiles para elementos como las plantillas.

  2. Tiempo de ejecución
    Estas afirmaciones se realizan utilizando la función assert() definida en <cassert>
    Las aserciones de tiempo de ejecución solo se evalúan en tiempo de ejecución. Y como señaló BoltBait, no se compilan si la NDEBUG macro ha sido definida.

  3. Estático
    Estas afirmaciones se realizan, como usted dijo, utilizando la macro ASSERT(), pero solo si está utilizando MFC. No conozco otra forma de hacer aserciones estáticas que formen parte del estándar C / C ++, sin embargo, la biblioteca Boost ofrece otra solución: static_assert.
    La función <=> de la biblioteca Boost es algo que se agregará en C ++ 0x estándar .

Como advertencia adicional, la función <=> que sugirió Ferruccio no tiene el mismo comportamiento que la macro MFC <=>. La primera es una aserción de tiempo de ejecución, mientras que la segunda es una aserción estática.

¡Espero que esto ayude!

La afirmación es (generalmente) solo depuración

El problema con " afirmar " es que generalmente está en binarios de depuración, y que algunos desarrolladores los usan como si el código todavía estuviera en producción.

Esto no es malo per se, ya que se supone que el código debe ser probado intensamente y, por lo tanto, los errores que producen la afirmación seguramente serán descubiertos y eliminados.

Pero a veces (¿la mayoría de las veces?), las pruebas no son tan intensas como se desea. No hablaré sobre un trabajo antiguo en el que tuvimos que codificar hasta el último minuto ( no preguntes ... A veces, los gerentes son solo ... Ejem ... ) ... ¿Cuál es el punto de una afirmación que agrega a un código que se compilará y se entregará como Release Binary al cliente en el próximo minuto?

Afirmar en (algunas) aplicaciones de la vida real

En nuestro equipo, necesitábamos algo para detectar el error y, al mismo tiempo, algo más para manejar el error. Y lo necesitábamos, potencialmente, en Release Build.

Assert detectará y manejará el error solo en la compilación de depuración.

Por lo tanto, agregamos una macro XXX_ASSERT, así como una macro XXX_RAISE_ERROR.

La macro XXX_ASSERT haría lo mismo que la macro ASSERT, pero se construiría tanto en Debug como en Release. Su comportamiento (escribir un registro, abrir un cuadro de mensaje, no hacer nada, etc.) podría controlarse mediante un archivo .INI, y ENTONCES, abortaría / saldría de la aplicación.

Esto se usó como:

bool doSomething(MyObject * p)
{
   // If p is NULL, then the app will abort/exit
   XXX_ASSERT((p != NULL), "Hey ! p is NULL !") ;

   // etc.
}
La macro

XXX_RAISE_ERROR solo " log " el error pero no intentaría manejarlo. Esto significa que podría registrar el mensaje en un archivo y / o abrir un cuadro de mensaje con el mensaje, y un botón para continuar y otro para iniciar una sesión de depuración (según la configuración del archivo .INI). Esto se usó como:

bool doSomething(MyObject * p)
{
   if(p == NULL)
   {
      // First, XXX_RAISE_ERROR will alert the user as configured in the INI file
      // perhaps even offering to open a debug session
      XXX_RAISE_ERROR("Hey ! p is NULL !") ;
      // here, you can handle the error as you wish
      // Than means allocating p, or throwing an exception, or
      // returning false, etc.
      // Whereas the XXX_ASSERT could simply crash.
   }

   // etc.
}

Un año después de su introducción en nuestras librerías, solo se está utilizando XXX_RAISE_ERROR. Por supuesto, no se puede usar en partes de la aplicación de tiempo crítico (tenemos un XXX_RAISE_ERROR_DBG para eso), pero en cualquier otro lugar, es bueno. Y los hechos de que uno puede usar cualquier manejo de errores preferido, y que se puede activar a voluntad, ya sea en la computadora del desarrollador, o el probador, o incluso el usuario, es bastante útil.

Para responder la pregunta en su segundo " edit " ;:

< afirmar.h > es el encabezado C

< cassert > es el encabezado de la biblioteca estándar de C ++ ... generalmente incluye < afirmar.h >

Para romper dentro del archivo que llamó la aserción, puede usar una macro personalizada que arroje una excepción o llame a __debugbreak:

#define MYASSERT(EXPR, MSG) if (!(EXPR)) throw MSG;

O:

#define MYASSERT(EXPR) if (!(EXPR)) __debugbreak();

Uso básico de afirmación

#include <cassert>

/* Some code later */
assert( true );

Notas de mejores prácticas

Las afirmaciones se usan para identificar estados de tiempo de ejecución que deberían ser verdaderos . Como resultado, se compilan en modo de lanzamiento.

Si tiene una situación en la que desea que una aserción siempre tenga éxito, puede pasarle falso. Por ejemplo:

switch ( someVal ):
{
case 0:
case 1:
  break;
default:
  assert( false ); /* should never happen */
}

También es posible pasar un mensaje a través de afirmar:

assert( !"This assert will always hit." );

Las bases de código maduras con frecuencia extienden la funcionalidad de afirmación. Algunas de las extensiones comunes incluyen:

  • Alternar afirma por módulo para localizar las pruebas.
  • Crear una macro de aserción adicional que se compila en la mayoría de las compilaciones de depuración. Esto es deseable para el código que se llama con mucha frecuencia (millones de veces por segundo) y es poco probable que sea incorrecto.
  • Permitir a los usuarios deshabilitar la afirmación actualmente afectada, todas las afirmaciones en la unidad de compilación o todas las afirmaciones en la base de código. Esto evita que se activen afirmaciones benignas, creando compilaciones inutilizables.

CRT específico de Microsoft afirma

#include <crtdbg.h>
#include <sstream>
...
// displays nondescript message box when x <= 42
_ASSERT(x > 42);
// displays message box with "x > 42" message when x <= 42
_ASSERTE(x > 42);
// displays message box with computed message "x is ...!" when x <= 42
_ASSERT_EXPR(
   x > 42, (std::stringstream() << L"x is " << x << L"!").str().c_str());

Hay una biblioteca de código abierto más avanzada llamada ModAssert, que tiene afirmaciones que funcionan tanto en Visual C ++ como en gcc. Probablemente también en otros compiladores, no estoy seguro. Toma algún tiempo aprenderlo, pero si quieres buenas afirmaciones que no dependan de MFC, míralas. Está en http://sourceforge.net/projects/modassert/

usa intellisense para abrirlo en Visual Studio (clic derecho)

// cassert standard header
#include <yvals.h>
#include <assert.h>

yvals.h es material de Windows. entonces, en lo que respecta a afirmar (), las dos formas de incluirlo son idénticas. es una buena práctica usar <cxxx> porque a menudo no es tan simple (ajuste de espacio de nombres y tal vez otra magia)

Esto se rompe en el sitio de la persona que llama ...

aquí hay un artículo que explica por qué no desea escribir esta macro usted mismo.

Aquí está mi iteración más reciente de una instalación de Aserción en C ++: http://pempek.net/articles/2013/11/17/cross-platform-cpp-assertion-library/

Es una biblioteca de 2 archivos que puede agregar fácilmente a su proyecto.

Para responder la tercera pregunta del autor de la pregunta: la primera razón por la que usamos " cassert " en lugar de " afirmar.h " Esto se debe a que, en el caso de C ++, existe un margen para el hecho de que el compilador de C ++ puede no almacenar las descripciones de las funciones en archivos de código, sino en un dll o en el compilador en sí. El segundo es que puede haber cambios menores en las funciones para facilitar las diferencias entre C y C ++, ya sea en el presente o en el futuro. Debido a que afirmar.h es una biblioteca C, la preferencia es usar & Quot; cassert & Quot; mientras que en C ++.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top