Trivial use of NSURLRequest/NSURLConnection causes memory leak

Discussion in 'iOS Programming' started by vegashacker, Oct 1, 2008.

  1. vegashacker macrumors newbie

    Joined:
    Apr 20, 2008
    #1
    I'm experiencing a consistent increase in the net number of objects (as determined by Instruments) when I try to do a simple asynchronous url request. Note that I do not see a leak detected visually, but when I look at the number in the "# Net" column, I see the number increasing each time I make a call to a server. I stripped out everything that I could to make the simplest example possible:

    In applicationDidFinishLaunching, add
    Code:
    	posty = [[Post alloc] init];
    Add an action method linked up to a simple button in the app:
    Code:
    -(IBAction) clicky:(id)sender {
    	[posty post];
    }
    
    Post.m looks like this:
    Code:
    -(void) post {
    	NSURLRequest* req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://google.com"]];
    	[theData release];
    	theData = nil;
    	theData = [[NSMutableData data] retain];
    	[[NSURLConnection alloc] initWithRequest:req delegate:self];	
    }
    
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
        [connection release];
    }
    
    To test, I click the button (slowly, to ensure a full request has finished) a few times until the allocations in Instruments seem to stabilize. After that point, with each click the # net allocs increases by by a few.

    Any ideas on what's causing this? I tried to follow the Apple Doc's example closely (and make it even more simple for the purposes of my debugging and this post).

    Thanks,
    Rob
     
  2. cemorris macrumors regular

    Joined:
    Oct 13, 2004
    #2
    My opinion

    I am no expert at objective c memory manangement as I still find some aspects of it confusing. I beleive your problem is in the post method. You are doing the following on the last line of the method.

    Code:
    [[NSURLConnection alloc] initWithRequest:req delegate:self];
    You should be doing a release on this afterwards before the post method ends.

    I.E.
    Code:
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:req delegate:self];
    [connection release];
    
    So for each post method you would be leaking one NSURLConnection. In general each time you call an alloc, that method is responsible for doing a release on it at some point. In this case since it is a local variable, you need to decide what you are going to do with it (release, autorelease) before the method ends. If others are going to use it (the initWithRequest method for example) they are responsible for doing a retain on it.

    It looks like you are doing a release at the end after the connection did finish loading, but are you guaranteed that it is the same object you initially created? I may have been copied at some point and you are seeing a different instance of the NSURLConnection object.

    From you code sample I do not see any case where you would be leaking any NSURLRequest objects

    As a side note, I find the memory management in objective c to be the most confusing of other languages that I have seen. I really wish the garbage collection feature would make its way into the iPhone.

    Hope this helps
     
  3. vegashacker thread starter macrumors newbie

    Joined:
    Apr 20, 2008
    #3
    Thanks for the reply, but I don't think this is the problem. See this Apple document (http://developer.apple.com/document...LoadingSystem/Tasks/UsingNSURLConnection.html). In it, they alloc the object and then release it in another method. The reason is that this is an asynchronous request. If you released the connection right after you created it, it wouldn't have time to finish (and in fact, the app crashes if you try this). It may be that you are right about the duplication of the object, but then how am I supposed to do it?

    I'm suspecting a bug, but I'd like someone else to independently verify that.
     
  4. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #4
    So what are the objects that are being allocated that cause your memory to increase? You can see the exact stack trace for each allocation in the timeline.

    I can tell you that NSURLConnection does a lot of things. It creates a background thread that I think doesn't go away. I haven't looked closely at its allocations but this might not be a problem.
     
  5. mpramodjain macrumors regular

    Joined:
    Nov 20, 2008
    Location:
    Banglore
    #5
    Any solution..

    Hi,

    I am also suffering with same problem. My application also consists of multiple http connection using a timer. This also shows the increase in #Net allocations and after some time the Histogram turns to pink and finally the app crashes with no memory leaks shown at all. Please help me if u found any solution...
     
  6. iPost macrumors regular

    Joined:
    Sep 28, 2003
    #6
    What I did

    In my code, I found that if I released the NSURLConnection object in the connectionDidFinishLoading delegate method, it showed up as a leak in Instruments.

    If I release it after a delay (outside of the connectionDidFinishLoading method), the leak went away.

    Or, you could just use [NSURLConnection connectionWithRequest:delegate:] instead of alloc/initWithRequest and don't worry about releasing it at all since it will be autoreleased. This doesn't leak either.
     
  7. mpramodjain macrumors regular

    Joined:
    Nov 20, 2008
    Location:
    Banglore
    #7
    Cache Policy

    I tried the above options ,but stil I am suffering with the problem.
    when i am starting my connection for every 15 secs using timer , the memory grows and grows. Leak Instrument showing no leaks, but showing the following are the Responsible callers, for the memory increment..

    1) sqlite3pageracquire
    2) ProcessCacheTasks(_CFUrlCache*)

    Thank u.
     
  8. mpramodjain macrumors regular

    Joined:
    Nov 20, 2008
    Location:
    Banglore
    #8
    nsurlcache

    I got the problem of #Net keeps on increasing solved by using the following code in application did finish loading function.:

    NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
    [NSURLCache setSharedURLCache:sharedCache];
    [sharedCache release];

    I think it cleans up the cache .

    But there is one more issue left behind, that is of #Allocation Histogram is turning from BLUE to Red as #Overall Allocation value keeps on increasing.

    And the Application gets crashed after a some time.

    Please help if any had faced this issued.
     
  9. BlueDevelop, Jul 13, 2011
    Last edited: Jul 13, 2011

    BlueDevelop macrumors newbie

    Joined:
    Jul 13, 2011
    #9
    Anyone found a soloution.

    Im struggling with the same problem as above.
    Been searching google like mad, can anyone tell me how to get rid of this memory leak?

    Edit:
    I now declared theConnection like NSURLConnection *theConnection; in the interface of the class.
    I then say:
    self.theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

    In the fail, receivedata and dealloc I have:
    self.theConnection = nil;

    this gets rid of the analyse warning, so I hope that is the way to do it.
     
  10. idelovski macrumors regular

    Joined:
    Sep 11, 2008
    #10
    BlueDevelop, unles you have the property declared with assign keyword, this is a leak:

    Code:
    self.theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
    Use temp variable or autorelease.
     
  11. BlueDevelop, Jul 15, 2011
    Last edited: Jul 15, 2011

    BlueDevelop macrumors newbie

    Joined:
    Jul 13, 2011
    #11
    I have @property(nonatomic, assign) NSURLConnection *theConnection;

    I tried using NSURLConnection *connection and releasing that.
    And I tried autorelease.

    With NSURLConnection *connection the analyser complains about leak.
    And with autorelease it is released before the actually data has been fetched.
     
  12. dtp23, Apr 20, 2012
    Last edited by a moderator: Apr 20, 2012

    dtp23 macrumors newbie

    Joined:
    Apr 20, 2012
    #12
    Clear cache

    I had the same problem, at the end of your request just add this line:
    Code:
    [[NSURLCache sharedURLCache] removeAllCachedResponses];
     

Share This Page