Pregunta

En C y C++ assert es un muy peso pesado de la rutina, de la escritura de un error stdout y terminar el programa.En nuestra aplicación hemos implementado una mucho más robusto de reemplazo para afirmar y le ha dado su propia macro.Cada esfuerzo ha sido hecho para reemplazar assert con nuestra macro, sin embargo, todavía hay muchas maneras assert puede ser presentada de nuevo (por ejemplo, del interior de las bibliotecas de terceros, ingenuo de la inyección, etc.)

Alguna sugerencia sobre cómo podemos reducir, limitar o incluso erradicar los usos de assert?La mejor respuesta será un compilador puede detectar para nosotros, así que no tienen que cuidar a la base de código tanto como lo hacemos actualmente.

¿Fue útil?

Solución

No estoy seguro de que realmente haya entendido el problema, en realidad. Afirma sólo son caros si se apagan, lo cual está bien de todos modos, ya que está ahora en una situación de excepción.

assert sólo se activa en versiones de depuración, a fin de utilizar la versión de lanzamiento de una biblioteca de terceros. Pero, en realidad, afirma que no se debe de apagarse cada momento.

Otros consejos

Puede ser útil para mejorar la facilidad afirmación incorporada (para proporcionar trazas de la pila, volcados de memoria, quién sabe). En ese caso, si usted está teniendo problemas para conseguir sus desarrolladores a seguir lo que las normas que tiene (como "lugar de uso assert() SUPER_ASSERT()" o lo que sea), sólo puede poner su propia cabecera assert.h en la ruta de inclusión por delante del directorio de ejecución del compilador de cabeceras.

que va a casi garantizar que cualquier persona que utilice la macro assert() norma obtendrá un error de compilación o recuperar su funcionalidad afirmación (dependiendo de lo que usted tiene su cabecera assert.h hacer).

Dependería (al menos en parte) de lo que está cambiando. Suponiendo que no le importa que imprimir su mensaje normal, y sobre todo quiere deshacerse de ella llamando abort(), usted podría considerar dejar assert() solo, y en lugar de definir su propia versión de abort().

En teoría, haciendo que no es portátil - pero en realidad, abort() es una función bastante normal en la biblioteca estándar, y si se vincula su propio lugar, se obtiene su comportamiento. A veces (especialmente algunos enlazadores de Microsoft) que tiene que hacer un poco de trabajo para conseguir el enlazador de cooperar en la sustitución de su abort() con los suyos, pero es rara vez muy difícil.

Creo que tu pregunta es totalmente válida.Si usted tiene implementado su propio control de errores puede que desee:

  1. Activar siempre afirma incluso en las versiones de lanzamiento.
  2. Implementar mejor de informes de error en caso de que una aserción desencadenantes.Puede que desee enviar informes de error o escribir en archivos de registro.

Dicho esto, no veo ninguna solución que funciona siempre.

  • Si tienes suerte, las bibliotecas de terceros uso de AFIRMAR las macros que se pueden redefinir sí mismo siempre que el archivo de definición de esta macro tiene algún tipo de #pragma once o #ifndef __HEADERFILE_H__ #define __HEADERFILE_H__ disposición en contra de varios de inclusión.Incluir el archivo de encabezado por separado, redefinir VALER y en lo que eres bueno.

  • Si se incluye directamente valer.h o cassert sólo se puede parchear el código, supongo.Hacer cambios mínimos en el código, guardar los cambios como el parche de archivos y cuando se actualiza la biblioteca de la esperanza de que los parches todavía funcionan.Agregar los parches para el control de versiones.

Si esto no funciona, a repensar la cuestión de si realmente se necesita interna afirma en las bibliotecas de terceros.La nave de la liberación se basa únicamente, esto elimina la afirma, y agrega su reivindica para comprobar la exactitud de los dentro de su código.Comprobar la validez de los valores de retorno.Si tal ASERCIÓN es activa, todavía se puede bucear en el código de terceros para ver lo que causó el problema.

Creo que la pregunta es válida.

Mi propia aserción se expande a asm ( "int3") si se activa, lo que equivale a un punto de ruptura. También encontré que mucho más útil para la depuración de una terminación sencilla.

I llamado simplemente se "ASSERT ()" en lugar de la normal "assert ()" y evitado el uso de assert () en absoluto.

El enfoque más obvia parece ser que dar su propia versión de afirmar su propio nombre, ligeramente diferente de assert(). A continuación, puede buscar en el texto, mirar a los mensajes de engarce, etc., para el "_assert" cadena literal y usted sabe que tiene un problema cuando lo ves.

En mi propio código, siempre uso Assert(), que se expande a mi propia función que realiza una afirmación, o se expande para ((void)0) para la versión de lanzamiento. El compilador convertir la expresión ((void)0) en la nada, pero todavía cuenta como una expresión. Por lo tanto

Assert(3 == x);

se convertirá en

((void)0);

y el punto y coma tiene un lugar a donde ir.

Por cierto, que una vez trabajó en una aplicación de interfaz gráfica de usuario, donde la aserción era un cuadro de diálogo emergente especial GUI modal. Tenías tres opciones: Ignorar, Ignorar para siempre, o se rompen. Ignorar ignoraría la aserción y seguir corriendo. Ignorar siempre sería establecer un indicador, y hasta que se reinicie el programa en el depurador, que afirman no dispararía más. Ruptura permitiría la aserción para entrar en el depurador.

No recuerdo cómo se garantiza que cada aserción tenía su propia bandera. Tal vez cuando escribió la aserción () llame había que especificar un número entero único? Sería bueno si era más automático que eso. Estoy bastante seguro de que el implmentation real fue de un vector de bits, y sería establecer el bit cuando eligió ignorar para siempre.

assert() se suele #define'd ser ((void) 0) para el código de liberación (#define NDEBUG), por lo que es ninguna sobrecarga en absoluto .

Cuando se utiliza una versión de prueba, es la sobrecarga de rendimiento perjudicar a su capacidad para la prueba sea realista?

Parece que falta el hecho de que el código de terceros es más probable escrito bajo el supuesto de comportamiento assert "estándar". Es decir. el código espera que el programa termina en la afirmación fallado. El código que sigue a la afirmación de que normalmente no puede y no funcionará correctamente si la condición afirmado se rompe. En 99 casos de cada 100 no funcionará en absoluto. En 99 casos de un total de 100 simplemente se colgará, es decir, el programa terminará de todas formas.

Para creer que reemplazando el comportamiento assert de código de terceros de alguna manera va a hacer el programa en vivo ya es ingenua en el mejor.

Si el código fuente está bajo su control:

#define NDEBUG
// Before
#include <assert.h>
// Or other header that includes assert.h

O utilizar encabezado precompilado o compilar opciones para definir NDEBUG.

Para binarios de tercera parte, utilizar la versión de liberación de ellos.

Encuentra assert en las cabeceras de la biblioteca (asumiendo que son archivos reales en el sistema de archivos) y sustituirla por una cosa no válido

// #define assert(condition) ... /* old definition */
#define assert(condition) ((condition) & "PLEASE DO NOT USE ASSERT" = 42)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top