2009-05-27 7 views
11

Me acaba de picar un molesto bug que se hizo oscuro por el comportamiento "enviar mensaje a nada está bien" en Objective-C.¿Hay alguna manera de atrapar los mensajes enviados a cero en Objective-C?

He visto Sending a message to nil?, y el consenso parece ser "así es como rodamos" en Objective-C.

Ahora, tal vez no tengo suficiente experiencia en Objective-C, pero parece que sería útil atrapar esto, porque no puedo pensar en una buena razón por la que esto debería estar sucediendo más de el tiempo. Sin embargo, podría ser una expresión de codificación a la que todavía no estoy acostumbrado.

Así que aparte de la comprobación de cero en todas partes, así:

assert(object != nil); 
[object message]; 

¿Hay una manera de hacer la trampa de tiempo de ejecución de esta condición, y advertir cuando object es nula?

+2

¿Por qué no intentar escribir en un idioma Objective-C, en lugar de trasladar expresiones idiomáticas de Java a Objective-C? – runako

+1

No lo sé, no codigo en Java. Claramente, otras personas lo han encontrado útil (ver respuesta a continuación). – Justicle

+1

s/Java/otro lenguaje de programación /. Aprender los modismos nativos de cualquier entorno generalmente lo hará más productivo en ese entorno. No luches contra tus herramientas. – runako

Respuesta

9

Puede usar ObjC undocumented trick or dtrace (vea los comentarios para la solución dtrace).

pid$1::objc_msgSend:entry 
/arg0==0/ 
{ 
    ustack(); 
} 
+5

Impresionante. Cuando mis ojos dejen de sangrar, lo intentaré :-) – Justicle

4

nil messagesaging se utiliza muy a menudo en ObjC. La gente puede pelear sobre si esto es bueno o malo; es solo algo a lo que tienes que acostumbrarte. Si tratas de romperlo con trucos, vas a romper el Cacao porque Cocoa lo usa. Hay algunos trucos (como el diciu publicado) que posibilitarán la depuración en situaciones en las que sospeche que no hay mensajes, pero parece que no pueden encontrarlo. Pero no puedes dejarlos en tu código (y la publicación de blog anterior lo deja claro). nil mensajes es demasiado común dentro de los marcos.

a su punto original, sin embargo, comparar:

- (void)doSomethingWith:(id)x { 
    NSAssert(x != nil, @"Don't pass me nil"); 
    [x something]; 
} 

vs

void Bar::DoSomething(Foo *x) { 
    assert(x != NULL); 
    if (x != NULL) { 
     x.something; 
    } 
} 

En ambos casos, es necesario poner a prueba, y en ambos casos el compilador no le avisará si no puedes probar La única diferencia es en qué casos se bloquea/afirma. Personalmente, escribo macros alrededor de NSAssert() que lo hacen siempre imprime un mensaje de registro si falla. Simplemente se bloquea en Debug. De esa manera, cuando un cliente me envía registros, puedo ver qué afirmaciones fallaron.

+0

Gracias Rob, simplemente incluí la afirmación dura para abreviar: no soy partidario de los bloqueos de versiones de lanzamiento y construcción. Creo que todo el asunto de enviar mensaje a nada es algo a lo que me voy a acostumbrar. Aún así, vale la pena preguntar y aprender un poco más sobre lo que sucede bajo el capó: ¡todos ganan! – Justicle

Cuestiones relacionadas