简体   繁体   中英

Objective-c for the iphone: Mystery memory leak

My application seems to have 4 memory leaks (on the device, running instruments).

The memory leaks seems to come from this code:

NSURL *url = [self getUrl:destination];
[destination release];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];

[request setHTTPMethod:@"GET"];
[request addValue:@"application/json" forHTTPHeaderField:@"content-type"];
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
[request release];

[connection release];

EDIT : added code for getUrl

- (NSURL *)getUrl:(NSString *)actionUrl
{
    NSString *rawUri = [[NSString alloc]initWithFormat:@"%@/%@", kBaseUrl, actionUrl];
    NSURL *url = [[[NSURL alloc] initWithString:rawUri] autorelease];
    [rawUri release];
    return url;
}

I am releasing all my objects as far as I can see but it's still showing this as the source of the 4 memory leaks.

This is on the Device running 3.1.3

Is it acceptable to have a few memory leaks in your app or do they all have to go?

EDIT : I've added autorelease to getUrl. However it still shows up with memory leaks

EDIT2 : The behaviour is rather strange. I launch the app and hit the button that makes this call once. 4 leaks are discovered. I press back and hit the button again, and keep doing this a few times, and still only 4 leaks. However, if I wait a few seconds and then press the button a gain a few more times, 9 leaks are discovered. It's not a small 128 byte leak, but it's 1.61KB at this point.

EDIT3 : Here is the connectionDidFinishLoading

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    SBJSON *jsonParser = [[SBJSON alloc] init];
    NSString *jsonString = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
    [receivedData setLength:0];
    [receivedData release];
    [self.delegate dataReceived:[jsonParser objectWithString:jsonString]]; // See method below
    [jsonParser release];
    [jsonString release];
}

The delegate gets the data, then transforms it (and in return passes it on to another delegate once the product is constructed)

- (void)dataReceived:(id)data
{
    NSMutableArray *myObjects = [[NSMutableArray alloc]init];
    ObjectFactory *objectFactory = [[ObjectFactory alloc]init];

    // Only one object
    if ([data isKindOfClass:[NSDictionary class]])
    {
        Object *object = [objectFactory buildObject:data];
        [myObjects addObject:object];
        [object release];
    }

    // Multiple objects
    if ([data isKindOfClass:[NSArray class]])
    {
        for (NSDictionary *objectSrc in data)
        {
            Object *object = [objectFactory buildObject:post];
            [myObjects addObject:object];
            [object release];
        }
    }
    [objectFactory release];
    [self.delegate objectsReceived:myObjects];
}

EDIT4 : Something I did notice is that the object "ConnectionObject" that contains the NSUrlConnection, never seem to be deallocated.

I put a breakpoint on dealloc which calls [connection release] This dealloc is never called. All the deallocs are called down the chain except for this one. I tried [connection cancel] in the "connectionDidFinishLoading" call to see if that helped but not at all.

This sure is a mystery to me...

You are releasing something you shouldn't:

NSURL *url = [self getUrl:destination]; 
// the returned url should have been autoreleased by the getUrl: method
// so you shouldn't release it again

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];

[url release]; // don't do this!

Remember that you should only release objects that were created using alloc , new or retain . Objects returned from other methods are always in an auoreleased state (by convention).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM