2009-05-27 10 views
11

Sono appena stato morso da un fastidioso bug che è stato reso oscuro dal comportamento "invia messaggio a nil è ok" in Objective-C.C'è un modo per intercettare i messaggi inviati a zero in Objective-C?

Ho visto Sending a message to nil? e il consenso sembra essere "questo è il modo in cui rotoliamo" in Objective-C.

Ora, forse non ho abbastanza esperienza in Objective-C, ma sembra che sarebbe utile per intercettare questo, perché non riesco a pensare a una buona ragione per cui questo dovrebbe accadere più di il tempo. Tuttavia, potrebbe essere solo un idioma di programmazione a cui non sono ancora abituato.

Così diverso da controllare per nil ovunque in questo modo:

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

C'è un modo per rendere la trappola runtime questa condizione, e avvertire quando object è pari a zero?

+2

Perché non provare a scrivere in un linguaggio Objective-C, invece di trasferire gli idiomi Java in Objective-C? – runako

+1

Non lo saprei, non codice in Java. Chiaramente altre persone hanno trovato questo utile (vedi risposta sotto). – Justicle

+1

s/Java/un altro linguaggio di programmazione /. Imparare gli idiomi nativi di qualsiasi ambiente ti renderà generalmente più produttivo in quell'ambiente. Non combattere i tuoi strumenti. – runako

risposta

9

È possibile utilizzare uno ObjC undocumented trick or dtrace (vedere i commenti per la soluzione dtrace).

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

Fantastico. Quando i miei occhi smettono di sanguinare farò un tentativo :-) – Justicle

4

nil messaggio viene utilizzato molto comunemente in ObjC. La gente può combattere se questo è buono o cattivo; è solo qualcosa a cui devi abituarti. Se provi a romperlo con trucchi, rompi Cocoa perché Cocoa lo usa. Ci sono alcuni trucchi (come diciu postati) che renderanno possibile eseguire il debug in situazioni in cui si sospetta che non ci siano messaggi, ma non riesco a trovarlo. Ma non puoi semplicemente lasciare quelli nel tuo codice (e il post del blog sopra lo rende chiaro). nil messaging è troppo comune all'interno dei framework.

al punto originale, però, confrontare:

- (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; 
    } 
} 

In entrambi i casi, è necessario testare, e in entrambi i casi il compilatore non avvisa se non riesci a testare. L'unica differenza è in quali casi si blocca/asserisce. Personalmente, scrivo macro intorno a NSAssert() che lo rendono sempre stampa un messaggio di registro se fallisce. Si blocca solo in Debug. In questo modo quando un cliente mi invia i log, posso vedere quali asserzioni falliscono.

+0

Grazie Rob, ho semplicemente incluso la dura affermazione per brevità - non sono un fan del crash di asserzione di build-build. Penso che l'intera questione send-message-to-nil sia qualcosa a cui mi ci abituerò. Tuttavia, vale la pena chiedere e imparare un po 'di più su cosa sta succedendo sotto il cofano - tutti vincono! – Justicle

Problemi correlati