2009-03-09 8 views
8

ich einen Absturz zu sehen, dass 10 oder 20 Sekunden passiert, nachdem eine POST-Anforderung I hat (didReceiveResponse, didReceiveData und connectionDidFinishLoading alle Feuer gut, bevor der Absturz passiert) fertig zu machen.iPhone SDK: Ausbuchen NSData mit NSMutableURLRequest Ergebnissen in mysteriösem Absturz

Dies ist der Code, den ich mit der Bitte an Sie:

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]; 

Was ist mit diesem Crash sehr merkwürdig ist, ist dies: wenn ich nicht setHTTPBody mit meinem NSData Objekt, setValue:@"application/json" für Content-Type telefoniere und setValue:requestDataLengthString für Content-Length, der Absturz tut nicht passieren. Ich bin völlig verwirrt, was passiert. Soweit ich das beurteilen kann, steht der Absturz in direktem Zusammenhang mit dem Senden eines NSData Objekts mit meiner Anfrage. Wenn es nicht zum Absturz bringen, die oberen Elemente in den Call-Stack für den Absturz (EXEC_BAD_ACCESS) sind die folgenden:

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

Kann jemand an etwas denken, das ich könnte falsch machen? Ich bin völlig ratlos, was ich falsch mache, wie ich es beheben kann oder wie ich es umgehen kann. Gibt es einen besseren Weg, um Daten zu senden als ich?

+0

Nur um etwas zu versuchen: Stürzt es immer noch ab, wenn Sie die Zeile [requestData release] entfernen? – squelart

Antwort

7

Sie sind richtig, dass in das Problem mit Ihrem NSData Objekt ist.Du Zuteilen es etwa so:

NSData* requestData = [jsonData dataUsingEncoding:NSUTF8StringEncoding]; 

nach den Regeln in der Memory Management Programming Guide for Cocoa angelegt, du bist nicht der Besitzer der Daten, so dass Sie sollten nicht später release darauf anrufen. dataUsingEncoding Aufrufe autorelease, so wird das Objekt release d das nächste Mal, wenn der Autorelease-Pool abläuft. Da Sie eine zusätzliche release hinzufügen, versucht der Autorelease-Pool release ein Objekt, das bereits freigegeben wurde, was den Absturz verursacht.

+0

Das war genau das. Vielen Dank! –

5

Sie haben ein automatisch freigegebenes Objekt freigegeben.

Entfernen Sie die Zeile [requestData release]; Sie brauchen es nicht. Es verursacht den Absturz, da die Daten von Ihnen freigegeben und dann wieder freigegeben werden, wenn die Daten gesendet werden, was zu viele Releases sind.

Im Allgemeinen rufen Sie die Freigabe für ein Objekt nicht auf, es sei denn, Sie weisen es zu, oder die Dokumentation besagt explizit, dass das zurückgegebene Objekt nicht automatisch freigegeben wurde. (was selten ist).

Mit diesem Code müssen Sie sich keine Sorgen machen, dass Sie ein automatisch freigegebenes Objekt verwenden, so weit der Speicher reicht, egal was Sie tun, der Speicher bleibt so lange, bis das zugrundeliegende Framework die Daten entlang der Leitung sendet .

Ich weiß nicht, ob es eine bessere Möglichkeit gibt, Daten zu posten - der Code, den Sie haben, sieht gut aus, außer dass die JSON-Daten wahrscheinlich in einer Zeichenfolge und einem Datenobjekt dupliziert werden, aber die Menge der Daten, die Sie sind Senden kann klein sein. Wenn dies nicht der Fall ist, sollten Sie die jsonData-Zeichenfolge sofort freigeben, nachdem Sie die Daten erstellt haben. (Das würde bedeuten, dass die jsonData-Zeichenfolge zusammen mit den Daten aus einem alloc/init-Aufruf stammen müsste). Oder machen Sie jsonData nicht zu einer Zeichenkette, sondern machen Sie sie von Anfang an als sinnvolle Daten, aber das kann peinlich sein.

--Tom

+0

Verdammt Autorelease :-) Ich denke, das ist das letzte Mal, dass ich diesen Fehler mache, haha. Vielen Dank! –

1

Überprüfen Sie auch den Anruf an [urlString release];. Wenn urlString mit etwas wie stringWithFormat oder stringwithString erstellt wurde, sollten Sie es nicht freigeben.