iPhone SDK:使用NSMutableURLRequest发布NSData会导致神秘的崩溃

时间:2009-03-09 23:46:56

标签: iphone objective-c

我发现在我发出的POST请求完成后10或20秒发生崩溃(didReceiveResponsedidReceiveDataconnectionDidFinishLoading在崩溃发生之前全部解雇了。

这是我用来发出请求的代码:

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

这次崩溃的奇怪之处在于:如果我不使用NSData对象调用 setHTTPBody,setValue:@"application/json"和{{1}调用Content-Type对于setValue:requestDataLengthString,崩溃会发生。我对发生的事情感到十分困惑。据我所知,崩溃直接与我的请求发送Content-Length对象有关。当它崩溃时,崩溃的调用堆栈中的顶部元素(NSData)如下:

  • EXEC_BAD_ACCESS
  • objc_msgSend
  • CFRelease
  • HTTPMessage::~HTTPMessage
  • _CFRelease

有谁能想到我可能做错了什么?我完全不知道我做错了什么,如何解决它,或者如何解决它。有没有比我正在做的更好的POST数据方式?

3 个答案:

答案 0 :(得分:7)

你的问题与你的NSData对象有关。你是这样分配它的:

NSData* requestData = [jsonData dataUsingEncoding:NSUTF8StringEncoding];

根据Memory Management Programming Guide for Cocoa中规定的规则,您不是数据的所有者,因此您以后不应该在其上调用releasedataUsingEncoding调用autorelease,因此下次自动释放池耗尽时对象将为release。因为您要添加额外的release,所以自动释放池将尝试release已经解除分配的对象,这会导致崩溃。

答案 1 :(得分:5)

您发布了一个自动释放的对象。

删除行[requestData release]; 你不需要它。它会导致崩溃,因为数据会由您释放,然后在数据发送完成时再次释放,这是一个太多的版本。

通常,除非您分配对象,否则不会调用对象的释放,或者文档明确表示返回的对象未自动释放。 (这很罕见)。

使用此代码,您无需担心使用自动释放的对象,就内存而言,无论您做什么,内存都将保持不变,直到底层框架沿着线路发送数据。

我不知道是否有更好的发布数据的方式 - 您看到的代码看起来还不错,除了json数据可能在字符串和数据对象中都重复,但是您发送的数据量可能很小。如果不是,您应该在创建数据后立即释放jsonData字符串。 (这意味着jsonData字符串必须来自alloc / init调用以及数据)。或者不要将jsonData作为一个字符串,只是从一开始就把它作为一个可以改变的数据,但这可能很尴尬。

- 汤姆

答案 2 :(得分:1)

检查对[urlString release];的通话。如果urlString是使用stringWithFormatstringwithString之类的内容创建的,则不应将其释放。