2009-03-09 8 views
8

sto vedendo un incidente che avviene 10 o 20 secondi dopo una richiesta POST faccio è terminata (didReceiveResponse, didReceiveData e connectionDidFinishLoading tutto il fuoco ben prima del crollo accade).iPhone SDK: inviare messaggi NSData con risultati NSMutableURLRequest in incidente misterioso

Questo è il codice che sto usando per fare la richiesta:

NSURL* url = [[NSURL alloc] initWithString:urlString]; 
[urlString release]; 

NSData* requestData = [jsonData dataUsingEncoding:NSUTF8StringEncoding]; 
NSString* requestDataLengthString = [[NSString alloc] initWithFormat:@"%d", [requestData length]]; 

NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:url]; 
[request setHTTPMethod:@"POST"]; 
[request setHTTPBody:requestData]; 
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 
[request setValue:requestDataLengthString forHTTPHeaderField:@"Content-Length"]; 
[request setTimeoutInterval:30.0]; 
[url release]; 
[requestData release]; 
[requestDataLengthString release]; 

m_URLConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 
[request release]; 

Cosa c'è di molto strano in questo incidente è questo: se io non chiamo setHTTPBody con il mio NSData oggetto, setValue:@"application/json" per Content-Type e setValue:requestDataLengthString per Content-Length, si verifica l'arresto non. Sono completamente perplesso su ciò che sta accadendo. Per quanto posso dire, l'arresto anomalo è direttamente correlato all'invio di un oggetto NSData con la mia richiesta. Quando lo fa crash, gli elementi superiori nella stack di chiamate per l'incidente (EXEC_BAD_ACCESS) sono i seguenti:

  • objc_msgSend
  • CFRelease
  • HTTPMessage::~HTTPMessage
  • _CFRelease
  • HTTPWriteFilter::~HTTPWriteFilter

Qualcuno può pensare a qualcosa che potrei stai sbagliando? Sono completamente a corto di ciò che sto facendo male, come risolverlo o come aggirarlo. C'è un modo migliore per i dati POST di quello che sto facendo?

+0

Solo per provare qualcosa: si blocca ancora se si rimuove la riga [requestData release]? – squelart

risposta

7

Sei corretta in quanto il problema è con il vostro NSData oggetto.Si sta assegnando in questo modo:

NSData* requestData = [jsonData dataUsingEncoding:NSUTF8StringEncoding]; 

Secondo le norme previste nel Memory Management Programming Guide for Cocoa, non sei un titolare dei dati, in modo da non dovrebbe essere chiamata release su di esso in seguito. dataUsingEncoding chiama autorelease, quindi l'oggetto sarà release d la prossima volta che il pool di autorelease si scarichi. Poiché stai aggiungendo un ulteriore release, il pool di autorelease sta tentando di eseguire il release un oggetto che è già stato deallocato, causando l'arresto anomalo.

+0

Era esattamente così. Grazie! –

5

È stato rilasciato un oggetto rilasciato automaticamente.

Rimuovere la riga [requestData release]; Non ne hai bisogno. Causa il crash, dal momento che i dati vengono rilasciati da te, quindi rilasciati nuovamente al termine dell'invio dei dati, ovvero un numero eccessivo di rilasci.

In generale, non si chiama release su un oggetto a meno che non lo si assegni oppure i documenti affermano esplicitamente che l'oggetto restituito non è autoreleased. (che è raro).

Con questo codice, non è necessario preoccuparsi che si stia utilizzando un oggetto autoreleased, per quanto riguarda la memoria, indipendentemente da ciò che si fa, la memoria rimarrà intorno fino a quando il framework sottostante invia i dati lungo il filo .

Non so se c'è un modo migliore per inviare dati - il codice che hai sembra ok, a parte i dati di JSON è probabilmente duplicato sia in una stringa che in un oggetto dati, ma la quantità di dati che sei l'invio potrebbe essere piccolo. Se non lo è, dovresti rilasciare esplicitamente la stringa jsonData subito dopo aver effettuato i dati. (Il che significherebbe che la stringa jsonData deve essere da una chiamata alloc/init, insieme ai dati). O non rendere jsonData come una stringa, basta renderlo come un dato nsmutable fin dall'inizio, ma potrebbe essere scomodo.

--Tom

+0

Autentica risata :-) Penso che questa sia l'ultima volta che farò questo errore, haha. Grazie! –

1

Controllare anche la chiamata a [urlString release];. se urlString è stato creato con qualcosa come stringWithFormat o stringwithString, non dovresti rilasciarlo.