1

I'm sitting here for at least half an hour to find a memory leak in my code. I just replaced an synchronous call to a (touch) method with an asynchronous one using NSOperationQueue. The Leak Inspector reports a memory leak after I did the change to the code. What's wrong with the version using NSOperationQueue?

Version without a MemoryLeak

-(NSData *)dataForKey:(NSString*)ressourceId_
{
   NSString *cacheKey = [self cacheKeyForRessource:ressourceId_]; // returns an autoreleased NSString*
   NSString *path = [self cachePathForKey:cacheKey]; // returns an autoreleased NSString*

   NSData *data = [[self memoryCache] objectForKey:cacheKey];
   if (!data)
   {
      data = [self loadData:path]; // returns an autoreleased NSData* 
      if (data)
      {
         [[self memoryCache] setObject:data forKey:cacheKey];
      }
   }
   [[self touch:path];
   return data;
}

Version with a MemoryLeak (I do not see any)

-(NSData *)dataForKey:(NSString*)ressourceId_
{
   NSString *cacheKey = [self cacheKeyForRessource:ressourceId_]; // returns an autoreleased NSString*
   NSString *path = [self cachePathForKey:cacheKey]; // returns an autoreleased NSString*

   NSData *data = [[self memoryCache] objectForKey:cacheKey];
   if (!data)
   {
      data = [self loadData:path]; // returns an autoreleased NSData* 
      if (data)
      {
         [[self memoryCache] setObject:data forKey:cacheKey];
      }
   }
   NSInvocationOperation *touchOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(touch:) object:path];
   [[self operationQueue] addOperation:touchOp];
   [touchOp release];
   return data;
}

And of course, the touch method does nothing special too. Just change the date of the file.

-(void)touch:(id)path_
{
   NSString *path = (NSString *)path_;
   NSFileManager *fm = [NSFileManager defaultManager];
   if ([fm fileExistsAtPath:path])
   {
      NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:[NSDate date], NSFileModificationDate, nil];
      [fm setAttributes: attributes ofItemAtPath:path error:nil];
   }
}
MacTouch
  • 709
  • 1
  • 9
  • 18
  • 1
    Finally solved it changing the way my NSOperation implementation does its job. I now just ensure everything is launched on the main thread and don't have to care about the presence of an autorelease pool in different places. The following answer was very helpful to refactor my code: http://stackoverflow.com/questions/1596160/asynchronous-methods-in-nsoperation – MacTouch Apr 29 '10 at 22:21
  • 1
    you should have posted it as an answer and also marked the questions as answered ;) – Felipe Sabino Jun 20 '11 at 12:05

0 Answers0