2012-06-08 5 views
7

Questo codice mi dà EXC_BAD_ACCESS, perché?perché questo codice fornisce EXC_BAD_ACCESS (usando IMP)

NSMutableDictionary *d = [[NSMutableDictionary alloc] init]; 
IMP imp= [d methodForSelector:@selector(setObject:forKey:) ]; 
imp(d, @selector(setObject:forKey:), @"obj", @"key"); 

Sto iniziando usando PIM, abeti provare .. senza fortuna. Non sono sicuro del motivo per cui ho ricevuto l'errore, anche .. in passato, quando ho ottenuto EXC_BAD_ACCESS, il messaggio è stato stampato sulla console, questa volta la linea di errore è evidenziata.

Alcune note: ARC è abilitata, XCode 4.3.2, il progetto utilizza Objective-C++ come de lingua predefinita/compilatore, questo codice è proprio all'inizio del progetto

grazie ragazzi

+0

Non riesco a riprodurre. Se lo metti in un nuovo progetto, ricevi ancora l'errore? – Chuck

+0

Sì, quello che ho trovato ... ARC è il problema. Prova a creare un nuovo progetto iOS con ARC abilitato. Quindi copia e incolla il codice da qualche parte (l'ho messo in applicazione ha fattoFinishLaunchingWithOptions :) – subzero

risposta

20

Devi lanciare correttamente il puntatore alla funzione o ARC non sa cosa dovrebbe fare. IMP è un puntatore a funzioni generiche che accetta un id, un selettore e un numero variabile di altri argomenti non definiti e restituisce un id. L'implementazione del metodo che stai tentando di chiamare richiede un ID, un selettore seguito esattamente da due parametri id e ha un tipo di reso vuoto. È possibile risolvere il problema modificando al seguente codice:

NSMutableDictionary* dict = [[NSMutableDictionary alloc] init]; 
void (*imp)(id, SEL, id, id) = (void(*)(id,SEL,id,id))[dict methodForSelector:@selector(setObject:forKey:)]; 
if(imp) imp(dict, @selector(setObject:forKey:), @"obj", @"key"); 

Si dovrebbe sempre verificare che effettivamente ottenuto un puntatore a funzione di nuovo prima di dereferenziarlo, come che sarebbe anche in crash. Il codice sopra funzionerà anche in un ambiente ARC. Inoltre, anche quando non stai usando ARC, devi sempre trasmettere i tuoi puntatori di funzione al prototipo reale piuttosto che a IMP. Non dovresti mai usare IMP. Altri posti che causerebbero problemi maggiori sono se il metodo restituisce una struct o se il metodo prende parametri in virgola mobile, ecc.

Buona abitudine: lanciare sempre i puntatori di funzione o creare typedef per loro se si trova la funzione sintassi del sintattore del puntatore .

+0

Grazie Jason. Ha funzionato come un fascino !. Domanda: perché causerebbe un grosso problema con struct o metodi con parametri in virgola mobile? Se potessi indicarmi un documento, sarei più felice. Ho appena trovato interessante l'argomento "runtime". – subzero

+1

Ha a che fare con le convenzioni di chiamata delle funzioni in C e come vengono passati i parametri. Dato che il compilatore non sa nulla dei parametri di IMP oltre i parametri 'self' e' _cmd', semplicemente spingerà altri parametri nello stack e si aspetta che la funzione chiamata sappia cosa fare con loro. Tuttavia, se la funzione chiamata si aspetta un float, sarà quasi sicuramente presente nel GPR (per ARM) o in un altro registro specifico per fp e non nello stack, ecc. È lo stesso per i tipi restituiti, le strutture sono gestite diversamente dai puntatori. –

1

Il problema è che IMP ha un tipo di ritorno di "id" che ARC tenterà di gestire. È necessario eseguire il cast del puntatore alla funzione per restituire un tipo di vuoto (coerente con il metodo che si sta chiamando):

NSMutableDictionary *d = [[NSMutableDictionary alloc] init]; 
    IMP imp= [d methodForSelector: @selector(setObject:forKey:)]; 
    void (*func)(__strong id,SEL,...) = (void (*)(__strong id, SEL, ...))imp; 
    func(d, @selector(setObject:forKey:), @"obj", @"key"); 
+0

'void (*) (id, SEL, ...)' non è il tipo giusto per il puntatore della funzione. È 'void (*) (id, SEL, id, id)'. Sebbene possa funzionare in questo caso particolare su alcune architetture con determinati tipi ('id'), in generale non è corretto. – newacct

+0

Questo ha funzionato. Grazie. – Felipe

Problemi correlati