2010-01-04 11 views
8

Estoy depurando una aplicación de iPhone muy segura (Xcode, Objective-C++ y simulador de dispositivo). En algunos casos, el error de afirmación terminaría la aplicación, en lugar de irrumpir en el depurador como era de esperar.¿Por qué assert simplemente termina un programa compilado para iPhone?

Hice una solución mediante la aplicación de un poco mi propia-valer a los efectos de:

#define AssertLite(b) if(!(b)) {asm {int 3}} 

(pelusa omitido), pero me pregunto si alguien alguna vez se encontró con esto. No pude determinar un patrón sobre cuándo se rompe y cuándo termina. El código no está enhebrado; todo lo que hace se hace en los controladores de eventos.

por qué sucede esto y cómo lo hago aserción de vainilla() se comportan como un punto de interrupción condicional que debe ser?

Respuesta

15

En primer lugar, ya se está trabajando en una aplicación para iPhone, que es mejor usar NSAssert() en lugar de la función de vainilla BSD afirman.

p. Ej. NSAssert(the_object, @"NIL object encountered");

La macro NSAssert lanzará una excepción Objective-C (NSInternalInconsistencyException) si la afirmación falla.

Dado que su objetivo es romper la excepción, el siguiente paso es hacer la pausa depurador de Xcode sobre excepciones Objective-C. Esto es probablemente una buena cosa para hacer de todos modos.

En la ventana Puntos de interrupción (Run-> Presentación-> elemento de menú puntos de interrupción), haga clic en donde dice "Haga doble clic para Symbol" para introducir el símbolo -[NSException raise]

La última cosa que tener cuidado es que fuera NSAsserts do no compilar en una compilación de lanzamiento. Eso significa que debe estar preparado para manejar la excepción en su aplicación, o necesita crear su propia macro que compila en compilaciones de lanzamiento.

Aquí está la macro que utilizo para compilar cabo aseveraciones de código de ejecución (nótese que luego uso HMAssert en mi código en lugar de NSAssert):

#ifdef DEBUG 
# define HMAssert(A,B) NSAssert(A,B) 
#else 
# define HMAssert(A,B) 
#endif 

Esto requiere una macro de depuración preprocesador para definir. Así es como poner esto en marcha:

  1. Haga clic en su proyecto en Xcode. Ese será el primer elemento en el panel de la izquierda, donde se enumeran los archivos de proyectos
  2. selecciona "Obtener información" en el menú contextual que aparece.
  3. Vaya a la pestaña "Crear".
  4. Asegúrese de que la "Configuración" esté configurada como "Depurar".
  5. Tipo de depuración en el campo junto a "preprocesador macros" en "GCC 4.2 - Preprocesamiento".
+0

Raw NSAssert no es una opción, ya que la base de código debe ser compilable para plataformas que no sean de Apple. Si empiezo #definiendo el assert() básico, también podría lanzar el mío, que comencé a hacer de todos modos. Gracias por el consejo. –

4

En primer lugar, si agrega el punto de interrupción de excepción ... en el Breakpoint Navigator (⌘6), el depurador se detendrá en las fallas de NSAssert, permitiéndole mirar la pila y entender qué salió mal.

Debe utilizar el estándar NSAssert. Si lo usa correctamente, no hay mucho que necesite crear manualmente; todo lo que menciona Mike es similar a la implementación predeterminada de NSAssert.

Debe ejecutar la configuración de lanzamiento con NS_BLOCK_ASSERTIONS establecido en sus encabezados precompilados (siga los pasos de Mike), para deshabilitar las aserciones. Si necesita más información sobre por qué hacerlo, consulte: http://myok12.wordpress.com/2010/10/10/to-use-or-not-to-use-assertions/

0

En Xcode 4 y iOS nuevo, NSAssert puede en realidad tomar una lista variable de parámetros. Esto puede ser útil para registrar algunos valores junto con la afirmación. La aserción compilación de salida (véase la respuesta de Mike arriba) podría definirse así:

#ifdef DEBUG 
# define DAssert(A, B, ...) NSAssert(A, B, ##__VA_ARGS__); 
#else 
# define DAssert(...); 
#endif 

Además, ya no hay opción de menú Ejecutar → → Mostrar puntos de interrupción. Consulte this post para configurar Xcode 4 para romper una afirmación como se define arriba.

0

Una vez vi un comportamiento diferente de las llamadas a assert() una vez. Fue causado por el compilador que recogió diferentes definiciones de macro en diferentes partes del proceso de compilación.

Una vez que las rutas de inclusión se enderezaron, todas funcionaron igual.

Cuestiones relacionadas