Observe la nota de man afirmar: "afirmar () se implementa como una macro; si la expresión probada tiene efectos secundarios, el comportamiento del programa será diferente dependiendo de si se define NDEBUG. Esto puede crear Heisenbugs que desaparecen cuando se activa la depuración ".
@ S.Lott ahora, las personas que buscan en Google encontrarán esta página como uno de los mejores resultados de búsqueda, proporcionando una buena respuesta revisada por pares a su pregunta y promoviendo Stack Overflow al mismo tiempo, ¡así que es un +1 de mi parte!
Matt Grum
66
Es un -1 de mi parte. El primer resultado de búsqueda debe ser la documentación que el OP debería haber consultado en primer lugar.
Carreras de ligereza en órbita
9
@LightnessRacesinOrbit. Llámame perezoso, pero prefiero usar las excelentes lecturas condensadas, resumidas y explicadas de la documentación que proporcionan los usuarios expertos de SO como tú. Mi sincero agradecimiento :)
Tyson Hilmer
Respuestas:
298
assertfinalizará el programa (generalmente con un mensaje que cita la declaración de aserción) si su argumento resulta ser falso. Se usa comúnmente durante la depuración para hacer que el programa falle más obviamente si ocurre una condición inesperada.
Por ejemplo:
assert(length >=0);// die if length is negative.
También puede agregar un mensaje más informativo para que se muestre si falla así:
assert(length >=0&&"Whoops, length can't possibly be negative! (didn't we just check 10 lines ago?) Tell jsmith");
O de esta manera:
assert(("Length can't possibly be negative! Tell jsmith", length >=0));
Cuando realiza una compilación de lanzamiento (sin depuración), también puede eliminar la sobrecarga de las assertdeclaraciones de evaluación definiendo la NDEBUGmacro, generalmente con un modificador de compilación. El corolario de esto es que su programa nunca debe confiar en la ejecución de la macro de aserción.
// BADassert(x++);// GOODassert(x);
x++;// Watch out! Depends on the function:assert(foo());// Here's a safer way:int ret = foo();assert(ret);
A partir de la combinación del programa que llama a abort () y no se garantiza que haga nada, las afirmaciones solo deben usarse para probar cosas que el desarrollador ha asumido en lugar de, por ejemplo, que el usuario ingrese un número en lugar de una letra (que debería ser manejado por otros medios).
"por lo assertgeneral genera una excepción" - en C ++ no genera "excepción" que llama abortar ... es un poco diferente.
Artyom
55
No creo que esta respuesta sea sobre los mismos lenguajes que la pregunta está etiquetada (C y C ++). En C y C ++, afirmar no genera una excepción, tiene paréntesis alrededor de su argumento y el #personaje no introduce un comentario.
Steve Jessop
Estas son sus opciones: haga la respuesta community-wiki y edite su pregunta eliminando las cosas viejas, pidiéndoles a otros que coloquen la información correcta. De esa manera, los votos negativos no afectarán a su representante, y las personas pueden mejorar la respuesta.
Johannes Schaub - litb
2
longitud> = 0 también resultará falso si la longitud es NaN
Andreas
1
Actualmente, en VS 2015, la afirmación con un mensaje de error no funcionará porque está fuera de servicio. Debería serassert("error message", expression)
Dooskington
102
La aserción comunicado equipo es análoga a la declaración Tras confirmar que en Inglés.
Bueno, no del todo. "Asegúrese de que la luz esté apagada" significa "verifique la luz y apáguela si está encendida", no "vea si la luz está apagada y si no, explote". Yo diría que "doble verificación" es una traducción más cercana.
Luke Maurer el
77
@Luke, eso ilustra las maravillas del idioma inglés, ya que el idioma ofrece muchas formas de decir lo mismo. Pero considere afirmar (longitud> 0). Entonces podemos traducir eso a "verificar dos veces que la longitud sea mayor que cero" o "asegurarse de que la longitud sea mayor que cero" . Aunque claramente ambas opciones funcionan, sigo prefiriendo la mía;)
Blake7
44
Bueno, pero la otra interpretación es " hacer que la longitud sea mayor que cero". Entonces hay un poco más de ambigüedad.
Luke Maurer
29
Es más análogo al verbo inglés "afirmar"
Steve Carter
De hecho, "asegurarse" podría interpretarse como "verificar, y si no está bien, cambiar".
Muchos compiladores ofrecen una macro afirmar (). La macro afirmar () devuelve VERDADERO si su parámetro evalúa VERDADERO y toma algún tipo de acción si evalúa FALSO. Muchos compiladores abortarán el programa en una afirmación () que falla; otros lanzarán una excepción
Una característica poderosa de la macro afirmar () es que el preprocesador lo colapsa en ningún código si DEBUG no está definido. Es de gran ayuda durante el desarrollo, y cuando se envía el producto final no hay penalización de rendimiento ni aumento en el tamaño de la versión ejecutable del programa.
P.ej
#include<stdio.h>#include<assert.h>void analyze (char*,int);int main(void){char*string="ABC";int length =3;
analyze(string, length);
printf("The string %s is not null or empty, ""and has length %d \n",string, length);}void analyze(char*string,int length){assert(string!= NULL);/* cannot be NULL */assert(*string!='\0');/* cannot be empty */assert(length >0);/* must be positive */}/**************** Output should be similar to ******************
The string ABC is not null or empty, and has length 3
¿De qué tratan esos "muchos compiladores"? MSVC y GCC cumplen ambos estándares en este caso. Qué compiladores no conformes: no tienen aserción; no imprima un mensaje y aborte cuando falla una afirmación; usa DEBUG en lugar del NDEBUG apropiado?
Steve Jessop el
lmao, por supuesto, es un sitio web llamado java-samples que se equivoca tanto.
underscore_d
6
La función afirmar () puede diagnosticar errores del programa. En C, se define en <assert.h>, y en C ++ se define en <cassert>. Su prototipo es
voidassert(int expression);
La expresión de argumento puede ser cualquier cosa que desee probar: una variable o cualquier expresión en C. Si expresión se evalúa como VERDADERO, afirmar () no hace nada. Si expresión se evalúa como FALSO, afirmar () muestra un mensaje de error en stderr y aborta la ejecución del programa.
¿Cómo se utiliza asir ()? Se utiliza con mayor frecuencia para rastrear errores del programa (que son distintos de los errores de compilación). Un error no impide que un programa se compile, pero hace que dé resultados incorrectos o que se ejecute incorrectamente (por ejemplo, bloqueo). Por ejemplo, un programa de análisis financiero que está escribiendo puede ocasionalmente dar respuestas incorrectas. Sospecha que el problema es causado por la tasa de interés variable que toma un valor negativo, lo que nunca debería suceder. Para verificar esto, coloque la declaración
afirmar (tasa de interés> = 0); en ubicaciones del programa donde se utiliza tasa de interés. Si la variable llega a ser negativa, la macro afirmar () lo alerta. Luego puede examinar el código relevante para localizar la causa del problema.
Para ver cómo funciona afirmar (), ejecute el programa de ejemplo a continuación . Si ingresa un valor distinto de cero, el programa muestra el valor y finaliza normalmente. Si ingresa cero, la macro afirmar () fuerza la terminación anormal del programa. El mensaje de error exacto que ve dependerá de su compilador, pero este es un ejemplo típico:
Error de aserción: x, lista de archivos 19_3.c, línea 13 Tenga en cuenta que, para que afirmar () funcione, su programa debe compilarse en modo de depuración. Consulte la documentación de su compilador para obtener información sobre cómo habilitar el modo de depuración (como se explica en un momento). Cuando luego compila la versión final en modo de lanzamiento, las macros afirmar () están deshabilitadas.
int x;
printf("\nEnter an integer value: ");
scanf("%d",&x);assert(x >=0);
printf("You entered %d.\n", x);return(0);
Ingrese un valor entero: 10
Ingresaste 10.
Ingrese un valor entero: -1
Mensaje de error: finalización anormal del programa
Su mensaje de error puede diferir, dependiendo de su sistema y compilador, pero la idea general es la misma.
Usted explicó cómo funciona su programa de muestra con afirmar. No cómo funciona la afirmación en sí misma. ¿Cómo termina el programa anormalmente? ¿Lanza algún tipo de excepción? ¿Que tipo? ¿Crea una señal especial? que señal ¿Pueden las afirmaciones ser "atrapadas" por algún tipo de mecanismo de prueba y captura de C ++?
Motti Shneor
4
Cosas como 'aumenta la excepción' y 'detiene la ejecución' podrían ser ciertas para la mayoría de los compiladores, pero no para todos. (Por cierto, ¿hay declaraciones de afirmación que realmente arrojan excepciones?)
Aquí hay un significado interesante, ligeramente diferente de aserción utilizado por c6x y otros compiladores de TI: al ver ciertas declaraciones de aserción, estos compiladores usan la información en esa declaración para realizar ciertas optimizaciones. Malvado.
Ejemplo en C:
int dot_product(short*x,short*y,short z){int sum =0int i;assert(((int)(x)&0x3)==0);assert(((int)(y)&0x3)==0);for( i =0; i < z ;++i )
sum += x[ i ]* y[ i ];return sum;}
Esto le dice al compilador que las matrices están alineadas en límites de 32 bits, por lo que el compilador puede generar instrucciones específicas hechas para ese tipo de alineación.
Entonces, ¿qué hacen si la afirmación es falsa y no se establece NDEBUG? Si esta es la versión de afirmar de <afirmar.h>, entonces el estándar requiere que imprima un mensaje y cancele. Obviamente, el estándar no dice que no se les permita optimizar en función de la verdad de la declaración, pero para cumplir, todavía tienen que abortar si es falso.
1 El encabezado <cassert>, descrito en (Tabla 42), proporciona una macro para documentar las aserciones del programa C ++ y un mecanismo para deshabilitar las comprobaciones de aserciones.
2 El contenido es el mismo que el encabezado de la biblioteca estándar C <afirmar.h>.
1 El encabezado <assert.h>define la macro de aserción y se refiere a otra macro, NDEBUGque no está definida por <assert.h>. Si NDEBUGse define como un nombre de macro en el punto del archivo fuente donde se incluye <afirmar.h>, la macro de afirmación se define simplemente como
#defineassert(ignore)((void)0)
La macro de aserción se redefine de acuerdo con el estado actual de NDEBUG cada vez que
<assert.h>se incluye.
2. La macro de aserción se implementará como una macro, no como una función real. Si se suprime la definición de macro para acceder a una función real, el comportamiento no está definido.
7.2.1 Diagnóstico del programa
7.2.1.1 La macro de aserción
Sinopsis
1)
#include<assert.h>voidassert(scalar expression);
Descripción
2 La macro de aserción coloca pruebas de diagnóstico en programas; se expande a una expresión vacía. Cuando se ejecuta, si la expresión (que tendrá un tipo escalar) es falsa (es decir, se compara igual a 0), la macro de aserción escribe información sobre la llamada particular que falló (incluido el texto del argumento, el nombre del archivo de origen, el número de línea de origen, y el nombre de la función de cerramiento - este último son, respectivamente, los valores de las macros de pre-procesamiento __FILE__y __LINE__y del identificador
__func__) en el flujo de error estándar en un formato definido por la implementación. 165) Luego llama a la función abortar.
Hay tres razones principales para utilizar la función afirmar () sobre la normal if if y printf
La función afirmar () se usa principalmente en la fase de depuración, es tedioso escribir, si no, con una instrucción printf cada vez que desee probar una condición que podría no llegar al código final.
En implementaciones de software grandes, la aserción es muy útil donde puede hacer que el compilador ignore las declaraciones de aserción utilizando la macro NDEBUG definida antes de vincular el archivo de encabezado para la función aserción ().
afirmar () es útil cuando está diseñando una función o algún código y desea hacerse una idea de los límites que el código funcionará y no funcionará y finalmente incluirá un if if para evaluarlo básicamente jugando con suposiciones.
Es una función que detendrá la ejecución del programa si el valor que ha evaluado es falso. Por lo general, está rodeado por una macro para que no se compile en el binario resultante cuando se compila con la configuración de lanzamiento.
Está diseñado para usarse para probar las suposiciones que ha hecho. Por ejemplo:
void strcpy(char* dest,char* src){//pointers shouldn't be nullassert(dest!=null);assert(src!=null);//copy stringwhile(*dest++=*src++);}
Lo ideal que desea es que pueda cometer un error en su programa, como llamar a una función con argumentos no válidos, y hacer clic en una afirmación antes de que falle (o no funcione como se esperaba)
¿Por qué no usamos if & else y agregamos información de registro?
Asad Khan el
1
Porque nunca deberías pasar un puntero nulo a strcpy. Es una de esas cosas que no deberían suceder. Si se ha pasado un puntero nulo, indica que algo en un nivel superior se ha estropeado. En el mejor de los casos, tendrá que bloquear el programa más allá del problema debido a valores de datos inesperados (ya sea que destino sea incorrecto o nulo).
Yacoby el
-5
Además, puede usarlo para verificar si la asignación dinámica fue exitosa.
Ejemplo de código:
int** p;
p =newint*[5];// Dynamic array (size 5) of pointers to intfor(int i =0; i <5;++i){
p[i]=newint[3];// Each i(ptr) is now pointing to a dynamic// array (size 3) of actual int values}assert(p);// Check the dynamic allocation.
No. newlanza una excepción en la falla de asignación a menos que especifique nothrow(que no hizo aquí). Además, su formato es extraño y exites malo.
Carreras de ligereza en órbita
Sí, tiene usted razón. Olvidé agregar no. Me encantaría ver cómo usará en lugar de salir
Sadikov
1
@Sadikov Cualquier otra persona manejaría una condición de error de este tipo utilizando un código que no se elimina por completo cuando se construye en modo de liberación , dejando a sus usuarios sin protección y a merced de un comportamiento indefinido si una condición previa no se cumple y, gracias a esto, es nunca comprobado y atrapado . assert()es solo para depurar y eliminar cosas que nunca, nunca, nunca sucederán, mucho antes de que se realice una versión de lanzamiento.
Respuestas:
assert
finalizará el programa (generalmente con un mensaje que cita la declaración de aserción) si su argumento resulta ser falso. Se usa comúnmente durante la depuración para hacer que el programa falle más obviamente si ocurre una condición inesperada.Por ejemplo:
También puede agregar un mensaje más informativo para que se muestre si falla así:
O de esta manera:
Cuando realiza una compilación de lanzamiento (sin depuración), también puede eliminar la sobrecarga de las
assert
declaraciones de evaluación definiendo laNDEBUG
macro, generalmente con un modificador de compilación. El corolario de esto es que su programa nunca debe confiar en la ejecución de la macro de aserción.A partir de la combinación del programa que llama a abort () y no se garantiza que haga nada, las afirmaciones solo deben usarse para probar cosas que el desarrollador ha asumido en lugar de, por ejemplo, que el usuario ingrese un número en lugar de una letra (que debería ser manejado por otros medios).
fuente
assert
general genera una excepción" - en C ++ no genera "excepción" que llama abortar ... es un poco diferente.#
personaje no introduce un comentario.assert("error message", expression)
La aserción comunicado equipo es análoga a la declaración Tras confirmar que en Inglés.
fuente
Echa un vistazo a
programa de ejemplo afirmar () en C ++
P.ej
fuente
La función afirmar () puede diagnosticar errores del programa. En C, se define en
<assert.h>
, y en C ++ se define en<cassert>
. Su prototipo esLa expresión de argumento puede ser cualquier cosa que desee probar: una variable o cualquier expresión en C. Si expresión se evalúa como VERDADERO, afirmar () no hace nada. Si expresión se evalúa como FALSO, afirmar () muestra un mensaje de error en stderr y aborta la ejecución del programa.
¿Cómo se utiliza asir ()? Se utiliza con mayor frecuencia para rastrear errores del programa (que son distintos de los errores de compilación). Un error no impide que un programa se compile, pero hace que dé resultados incorrectos o que se ejecute incorrectamente (por ejemplo, bloqueo). Por ejemplo, un programa de análisis financiero que está escribiendo puede ocasionalmente dar respuestas incorrectas. Sospecha que el problema es causado por la tasa de interés variable que toma un valor negativo, lo que nunca debería suceder. Para verificar esto, coloque la declaración
afirmar (tasa de interés> = 0); en ubicaciones del programa donde se utiliza tasa de interés. Si la variable llega a ser negativa, la macro afirmar () lo alerta. Luego puede examinar el código relevante para localizar la causa del problema.
Para ver cómo funciona afirmar (), ejecute el programa de ejemplo a continuación . Si ingresa un valor distinto de cero, el programa muestra el valor y finaliza normalmente. Si ingresa cero, la macro afirmar () fuerza la terminación anormal del programa. El mensaje de error exacto que ve dependerá de su compilador, pero este es un ejemplo típico:
Error de aserción: x, lista de archivos 19_3.c, línea 13 Tenga en cuenta que, para que afirmar () funcione, su programa debe compilarse en modo de depuración. Consulte la documentación de su compilador para obtener información sobre cómo habilitar el modo de depuración (como se explica en un momento). Cuando luego compila la versión final en modo de lanzamiento, las macros afirmar () están deshabilitadas.
Ingrese un valor entero: 10
Ingresaste 10.
Ingrese un valor entero: -1
Mensaje de error: finalización anormal del programa
Su mensaje de error puede diferir, dependiendo de su sistema y compilador, pero la idea general es la misma.
fuente
Cosas como 'aumenta la excepción' y 'detiene la ejecución' podrían ser ciertas para la mayoría de los compiladores, pero no para todos. (Por cierto, ¿hay declaraciones de afirmación que realmente arrojan excepciones?)
Aquí hay un significado interesante, ligeramente diferente de aserción utilizado por c6x y otros compiladores de TI: al ver ciertas declaraciones de aserción, estos compiladores usan la información en esa declaración para realizar ciertas optimizaciones. Malvado.
Ejemplo en C:
Esto le dice al compilador que las matrices están alineadas en límites de 32 bits, por lo que el compilador puede generar instrucciones específicas hechas para ese tipo de alineación.
fuente
C ++ 11 N3337 borrador estándar
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
19.3 Afirmaciones
C99 N1256 borrador estándar
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
7.2 Diagnóstico <afirmar.h>
7.2.1 Diagnóstico del programa
7.2.1.1 La macro de aserción
fuente
Hay tres razones principales para utilizar la función afirmar () sobre la normal if if y printf
La función afirmar () se usa principalmente en la fase de depuración, es tedioso escribir, si no, con una instrucción printf cada vez que desee probar una condición que podría no llegar al código final.
En implementaciones de software grandes, la aserción es muy útil donde puede hacer que el compilador ignore las declaraciones de aserción utilizando la macro NDEBUG definida antes de vincular el archivo de encabezado para la función aserción ().
afirmar () es útil cuando está diseñando una función o algún código y desea hacerse una idea de los límites que el código funcionará y no funcionará y finalmente incluirá un if if para evaluarlo básicamente jugando con suposiciones.
fuente
Es una función que detendrá la ejecución del programa si el valor que ha evaluado es falso. Por lo general, está rodeado por una macro para que no se compile en el binario resultante cuando se compila con la configuración de lanzamiento.
Está diseñado para usarse para probar las suposiciones que ha hecho. Por ejemplo:
Lo ideal que desea es que pueda cometer un error en su programa, como llamar a una función con argumentos no válidos, y hacer clic en una afirmación antes de que falle (o no funcione como se esperaba)
fuente
Además, puede usarlo para verificar si la asignación dinámica fue exitosa.
Ejemplo de código:
Similar a:
fuente
new
lanza una excepción en la falla de asignación a menos que especifiquenothrow
(que no hizo aquí). Además, su formato es extraño yexit
es malo.assert()
es solo para depurar y eliminar cosas que nunca, nunca, nunca sucederán, mucho antes de que se realice una versión de lanzamiento.