0

We've integrated facebook into an application to upload photos. This has been working great but recently using the XCode Alloc tool to track down any memory leaks we've discovered what seems to be an awful one. We are running an upload process in a separate dispatch thread. Then we're loading our facebook upload method in an auto release pool. When the upload gets called, the image goes on it's way to the appropriate FB profile. But, while uploading an NSKeyValueMethodForPattern gets created and holds about 500KB. Then, the big one, -[NSConcreteMutableData appendBytes:length] get's created and consumes about 4.5MB depending upon the image size. These two are created for each uploaded image and NEVER RELEASED! I'm at a loss with this. The alloc tool points to the below as the culprit

- (FBRequest*)openUrl:(NSString *)url params:(NSMutableDictionary *)params 
           httpMethod:(NSString *)httpMethod delegate:(id<FBRequestDelegate>)delegate 
{
    [params setValue:@"json" forKey:@"format"];
    [params setValue:kSDK forKey:@"sdk"];
    [params setValue:kSDKVersion forKey:@"sdk_version"];
    if ([self isSessionValid]) {
        [params setValue:self.accessToken forKey:@"access_token"];
    }

    [_request release];
    _request = [[FBRequest getRequestWithParams:params
                                     httpMethod:httpMethod
                                       delegate:delegate
                                     requestURL:url] retain];
    [_request connect]; // <<<< SAYING THIS IS 100% cause
    return _request;
}

Here is the code we're using to create the thread and "release" pool to process and upload the image.

backgroundQueue = dispatch_queue_create("com.somecomp.appnameo.bgqueue", NULL);  

dispatch_async(backgroundQueue, ^(void) {
    NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
    NSData *imageNSData = [NSData dataWithContentsOfFile:[NSString stringWithFormat:@"%@/%@", docDir, self.fileName]];
    UIImage *img  = [[UIImage alloc] initWithData:imageNSData];

    fbResponse = 0;
    //[facebook requestWithGraphPath:@"me" andDelegate:self];
    [[delegate facebook] requestWithGraphPath:@"me/permissions" andDelegate:self];
    NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                   //@"Sent From Some APP!", @"name",
                                   self.postTitle, @"caption",
                                   // string, @"description",
                                   img, @"picture",
                                   //@"my photo's caption text here.", @"message",
                                   nil];

    [img release];

    [[delegate facebook] requestWithMethodName:@"photos.upload"
                                     andParams:params
                                 andHttpMethod:@"POST"
                                   andDelegate:self];
    [loopPool drain];
}); 

Is there anything else I can do to release these mem hogs? I'm not a novice at this stuff but I'm at a loss with this. Any help here would be fantastic!

Thank you! - Jim

WrightsCS
  • 50,551
  • 22
  • 134
  • 186
mejim707
  • 431
  • 3
  • 16
  • When did you last update your FBConnect code? Look at that method on github, line 167: https://github.com/facebook/facebook-ios-sdk/blob/master/src/Facebook.m – danh Apr 13 '12 at 23:55
  • I just updated the code last night, and had all sort of recursion issues, come to find out I updated right into a recursion bug. I've since updated again after loosing 5 hours of my life. Still having the same issue. – mejim707 Apr 14 '12 at 00:28

1 Answers1

0

See my comment about the FBConnect code being out of date, but I doubt that the older versions had such an egregious leak (for every connection).

The thing that draws suspicion is the asynch invocation. FB's connection is already operating asynch, so I think you should leave that request on the main. Your block is finishing right away, because the requestWithMethod is returning right away.

danh
  • 62,181
  • 10
  • 95
  • 136
  • You make a very good point here. I'm going to try to send this back to the main, but, I put it on a secondary thread because I use a wait timer to wait for a response from Facebook before continuing. I want to mark the photos having been uploaded or not. If not uploaded I want to alert the user. Is there perhaps a more appropriate method? The timers, if used on the main thread, cause the app to pause while a wait is in place. On the secondary thread however the waits are transparent to the user and the app behaves quick and seamless. Thank you! – mejim707 Apr 14 '12 at 00:31
  • I've tried this and even though I'm not threading the upload it builds men allocation exactly the same. 8 images = about 80MB allocated. I have no clue at this point what to do. – mejim707 Apr 14 '12 at 22:24
  • Have you run the static analyzer? Product->Analyze. This might provide some better clues. – danh Apr 14 '12 at 23:31
  • Yes we've done this and all is well. I don't understand. Could this just be the simulator holding zombies? We have zombies disabled – mejim707 Apr 15 '12 at 00:32
  • I've still been struggling with this. I've just confirmed that the men releases after about 4 minutes. This occurs in steps down. So it you're uploading 4 images at 30 seconds apart the men will release 30 seconds apart without touching the app. Just watching the allocations tool and noticing this behavior. Is this normal or shouldn't it release right away if Zombies are not enabled. – mejim707 Apr 15 '12 at 18:54