我发现在我发出的POST请求完成后10或20秒发生崩溃(didReceiveResponse
,didReceiveData
和connectionDidFinishLoading
在崩溃发生之前全部解雇了。
这是我用来发出请求的代码:
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数据方式?
答案 0 :(得分:7)
你的问题与你的NSData
对象有关。你是这样分配它的:
NSData* requestData = [jsonData dataUsingEncoding:NSUTF8StringEncoding];
根据Memory Management Programming Guide for Cocoa中规定的规则,您不是数据的所有者,因此您以后不应该在其上调用release
。 dataUsingEncoding
调用autorelease
,因此下次自动释放池耗尽时对象将为release
。因为您要添加额外的release
,所以自动释放池将尝试release
已经解除分配的对象,这会导致崩溃。
答案 1 :(得分:5)
您发布了一个自动释放的对象。
删除行[requestData release]; 你不需要它。它会导致崩溃,因为数据会由您释放,然后在数据发送完成时再次释放,这是一个太多的版本。
通常,除非您分配对象,否则不会调用对象的释放,或者文档明确表示返回的对象未自动释放。 (这很罕见)。
使用此代码,您无需担心使用自动释放的对象,就内存而言,无论您做什么,内存都将保持不变,直到底层框架沿着线路发送数据。
我不知道是否有更好的发布数据的方式 - 您看到的代码看起来还不错,除了json数据可能在字符串和数据对象中都重复,但是您发送的数据量可能很小。如果不是,您应该在创建数据后立即释放jsonData字符串。 (这意味着jsonData字符串必须来自alloc / init调用以及数据)。或者不要将jsonData作为一个字符串,只是从一开始就把它作为一个可以改变的数据,但这可能很尴尬。
- 汤姆
答案 2 :(得分:1)
检查对[urlString release];
的通话。如果urlString
是使用stringWithFormat
或stringwithString
之类的内容创建的,则不应将其释放。