¿Cómo pueden NSLogs hacer que el código no se bloquee?

Tuve un crash exc_bad_access bastante interesante hoy. Después de mucha excavación, se me ocurrió la siguiente información (ejecutándose en un simulador):

Si solo ejecutara el código, la aplicación se bloquearía aleatoriamente en un punto aleatorio mientras se cargan datos en mi object gestionado. Por lo que pude decir, siempre se bloqueaba cuando cargué datos en el object gestionado, no en las secciones que se convirtieron de mi dict JSON a los datos en el object realmente utilizado (de cadenas y NSNulls a ints / floats y nils)

Las colisiones random son, por supuesto, malas, así que traté de pasar por el process en el depurador, pero eso no resultó práctico, estaba procesando MUCHOS objects, así que pisarlos uno por uno simplemente no " t trabajo Así que decidí agregar algunos NSLogs para rastrear el process y tratar de detectar un patrón de esa manera.

Solucionado al instante el choque.

Solo un NSLog, en cualquier parte del process, evitó el locking.

Finalmente rastré mi path por la traza de stack y encontré el problema real: estaba accediendo al object gestionado en un entorno de subprocesss, pero NO desde el método performBlockAndWait: MOC asociado. En ese momento, el crash fue increíblemente obvio para mí, me sorprendió que no tuviera más problemas antes. Estoy dispuesto a apostar que entre tener un set de datos de testing 'pequeño' de 2-3 objects y tener el código de debugging allí con NSLogs, el error se ocultó bastante efectivamente antes … pero la pregunta sigue siendo:

¿Por qué un NSLog evita que la aplicación se bloquee? ¿Cómo podría una pieza de código sin efectos secundarios cambiar la ejecución del rest de la aplicación? ¡Esto no tiene sentido!

Sorprendentemente, esta es una situación bastante común: la he visto más de una vez cuando habilitar el logging en un lugar aparentemente sin relación resolvería instantáneamente un problema de time en otro lugar.

La razón de esto es que NSLog , al igual que muchas otras funciones de salida, tiene synchronization interna. Existe un mutex en alguna parte que protege el acceso a los búferes internos de NSLog , ya sea en el propio NSLog o en una de las bibliotecas de E / S que utiliza. Esta synchronization permite a las personas que llaman usar NSLog de varios subprocesss. Es esta synchronization la que cambia el time de su progtwig, lo que afecta a una condición de carrera y, finalmente, resuelve un choque.

¿Por qué un NSLog evita que la aplicación se bloquee? ¿Cómo podría una pieza de código sin efectos secundarios cambiar la ejecución del rest de la aplicación? ¡Esto no tiene sentido!

De hecho, esto tiene sentido. De Verdad.

Un solo NSLog obliga a imprimir algo en su console, toma una fracción de segundos y entre su procesamiento en algo se termina y el fallo (puede deberse a la falta de disponibilidad de input) no más.

Su error puede deberse a una llamada asincrónica. Su próximo process comienza antes de terminar el anterior. Y su próximo process necesita datos del process previo. NSLog consume algo de time.