2011-12-13 17 views
6

Un amigo mío descubrió un comportamiento extraño con NSDictionary, y tengo curiosidad de por qué sucede. Considere el siguiente código:¿Por qué parece que se cuelga esta llamada de Objective C?

NSDictionary *dict = [[NSDictionary alloc] init]; 

// Oops, we can't mutate an NSDictionary 
[dict setObject:[[NSNull alloc] init] forKey:@"test"]; 
NSLog(@"Set"); 

El código produce una advertencia sobre la compilación que " 'NSDictionary' puede no responder a 'setObject: forKey:'". Eso es todo bien y bueno, y si lo ejecuta de todos modos, obtendrá esta salida en la consola:

- [__ NSCFDictionary setObject: forKey:]: mutación de método envió a objeto inmutable

Nuevamente, exactamente lo que esperaría que sucediera. Sin embargo, en este punto la aplicación no falla o termina debido a una excepción no detectada. El método setObject: forKey: simplemente nunca regresa y la aplicación parece bloquearse; el siguiente NSLog nunca se ejecuta. Si intenta pasar al método usando GDB, parece que la depuración parece finalizar, pero sin ningún mensaje de error explícito. La aplicación continúa ejecutándose, pero el depurador no proporciona ninguna pista sobre en qué parte del código está "trabada" la ejecución.

¿Qué está pasando aquí? ¿Qué está haciendo realmente la aplicación en este caso y por qué no se bloquea con una NSInternalInconsistencyException o algo por el estilo?

Editar: Para aquellos que han pedido, estoy ejecutando XCode 4.1 en OS X Lion (10.7.2), compilando con "Apple LLVM compiler 2.1." Estoy usando todas las configuraciones predeterminadas que obtienes con un nuevo proyecto Cocoa en XCode 4. Experimento el mismo comportamiento que no se bloquea, independientemente de si depuro el programa o simplemente "Ejecuto". Cambiar de la construcción de Debug a la versión de lanzamiento no hace diferencia. Incluso puedo ubicar el archivo .app de forma manual en Finder y hacer doble clic en él para ejecutarlo fuera de XCode, y aún así no se cuelga.

+1

Intenta ejecutarlo no debajo del depurador; Apuesto a que se bloquea duro. Encuentro que el entorno del depurador puede tener algunos efectos inesperados en el entorno de tiempo de ejecución, especialmente en torno a las excepciones y lo que sucede cuando los golpeas. –

+2

Cuando se lanza la excepción, el control se reanudará con lo que sea que atrape la excepción, * no * la siguiente línea después de la excepción. En su ejemplo, ya sea el depurador o las entrañas del tiempo de ejecución, "atrapó" la excepción. En cualquier caso, no esperaría que ocurriera el NSLog después de -setObject: forKey: lanzó una excepción. –

+0

@VincentGable: De acuerdo, si el programa fallara, no me sorprendería en absoluto que no se llamara al NSLog. Lo que me sorprende es que no se bloquea ni avanza a la siguiente línea. Parece que debería hacer una o la otra. Para aquellos que me lo han preguntado, he actualizado la pregunta con algunos detalles adicionales sobre el entorno en el que me estoy ejecutando. –

Respuesta

1

Las excepciones no bloquean los programas de AppKit. NSApplication instala un manejador de excepciones predeterminado que detecta excepciones que su código no detecta. Luego simplemente vuelves al runloop como siempre.

Muchas aplicaciones tienen este comportamiento. Es una causa común de inexplicables ventanas/vistas en blanco. Si ocurre una excepción antes de que una vista logre finalizar el dibujo, la vista estará en blanco, pero la aplicación no se bloqueará. Las excepciones solo provocan un bloqueo si cambia deliberadamente el controlador de excepción predeterminado para que se bloquee.

+0

Gracias, esto en su mayoría responde a mi pregunta. Sin embargo, una cosa de la que todavía estoy confundido es por qué no puedo ver la aplicación volver al bucle de evento principal después de que se captura la excepción. ¿O eso ocurre en un hilo diferente? No estoy tan familiarizado con el funcionamiento interno de AppKit. –

Cuestiones relacionadas