I'm seeing a crash that happens 10 or 20 seconds after a POST request I make has finished (didReceiveResponse
, didReceiveData
and connectionDidFinishLoading
all fire well before the crash happens).
This is the code I'm using to make the request:
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];
What's very odd about this crash is this: if I do not call setHTTPBody with my NSData
object, setValue:@"application/json"
for Content-Type
and setValue:requestDataLengthString
for Content-Length
, the crash does not happen. I'm completely perplexed as to what is happening. As far as I can tell, the crash is directly related to sending an NSData
object with my request. When it does crash, the top elements in the call stack for the crash (EXEC_BAD_ACCESS
) are the following:
objc_msgSend
CFRelease
HTTPMessage::~HTTPMessage
_CFRelease
HTTPWriteFilter::~HTTPWriteFilter
Can anyone think of something I might be doing wrong? I'm completely at a loss for what I'm doing wrong, how to fix it, or how to work around it. Is there a better way to POST data than the way I'm doing?
You are correct in that the problem is with your NSData
object. You're allocating it like so:
NSData* requestData = [jsonData dataUsingEncoding:NSUTF8StringEncoding];
According to the rules laid out in the Memory Management Programming Guide for Cocoa, you're not an owner of the data, so you shouldn't be calling release
on it later on. dataUsingEncoding
calls autorelease
, so the object will be release
d the next time the autorelease pool drains. Because you're adding an extra release
, the autorelease pool is going to try to release
an object which has already been deallocated, which is causing the crash.
You released an auto released object.
Remove the line [requestData release]; You don't need it. It causes the crash, since the data gets released by you, then released again when the data is done sending, which is one too many releases.
In general, you don't call release on an object unless you alloc it, or the docs explicitly say that the returned object is not autoreleased. (which is rare).
With this code, you don't need to worry that you are using an autoreleased object, as far as memory goes, no matter what you do, the memory will stay around until the underlying framework sends the data along the wire.
I don't know if there is a better way to post data - the code you have looks ok, other than the json data is likely duplicated in both a string and a data object, but the amount of data you are sending may be small. If it isn't you should expicitly release the jsonData string right after you make the data. (Which would mean that the jsonData string wuld have to be from an alloc/init call, along with the data). Or don't make the jsonData as a string, just make it as an nsmutable data right from the start, but that may be awkward.
--Tom
Check the call to [urlString release];
too. if urlString
was created with something such as stringWithFormat
or stringwithString
, you should not release it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With