开发者

Memory leak for uiimage

I'm getting heavy leak in UIImage. Could you please help me?

-(UIImage*)getImage{
  return [self getForrrrImage];
}

-(UIImage*)getForrrrImage{
  NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
  UIImage *imageResult=nil;
  if(index>=0 && index<[imagesPatchs count]){
    NSString *key=[imagesPatchs objectAtIndex:index];
    if(small)
      imageResult=[savedImagesDic objectForKey:key];

    if(!imageResult){
      NSRange range=[key rangeOfString:@"test_bg"];
      if(range.location!=NSNotFound){
        NSString *filePath1;
        if(small){
          NSString *str=[[NSString alloc] initWithFormat:@"%@_small",key];
          filePath1=[[NSBundle mainBundle] pathForResource:str ofType:@"jpg"];
          [str release];
        }
        else
          filePath1=[[NSBundle mainBundle]pathForResource:key ofType:@"jpg"];
        if(filePath1){
          imageResult=[self createImag开发者_开发问答eFromFile:filePath1];
          if(small){
            [savedImagesDic setObject:imageResult forKey:key];

          }
        }
      }

      else{

        NSString *filePath;
        if(small)
          filePath=[[NSString alloc]initWithFormat:@"%@/%@_small.png", DOCUMENTS_FOLDER, key];
        else
          filePath=[[NSString alloc]initWithFormat:@"%@/%@.png", DOCUMENTS_FOLDER, key];

        if([[NSFileManager defaultManager] fileExistsAtPath:filePath]){
          imageResult=[self createImageFromFile:filePath];
          if(small){
            if(imageResult){
              [savedImagesDic setObject:imageResult forKey:key];
              [imageResult release];
            }
            else {
              imageResult=[UIImage alloc];
            }

          }
          else{
            if(!imageResult)
              imageResult=[UIImage alloc];

          }
        }

        [filePath release];
      }
    }
  }
  else
    imageResult=[UIImage alloc];
  [pool drain];

  return imageResult;
} 

-(UIImage*)createImageFromFile:(NSString*)filePath{

  NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];

  UIImage *imageResult=nil;
  NSData *data=[[NSData alloc]initWithContentsOfFile:filePath options:NSUncachedRead error:nil];
  imageResult=[[UIImage alloc] initWithData:data] ;  ----->Heavy memory leak

  [data release];
  [pool drain];
  return imageResult;  

}


Instead of

[[UIImage alloc] initWithData: data];

You might try

[UIImage imageWithData: data];

This would make sure that you do not need to care about releasing the object because you use the class method which initializes the Image for you already.

And then you should also shoot for autoreleases. Like

[[[UIImage alloc] initWithData: data] autorelease]

Just as an example.


Just go through every createImageFromFile and make sure you release afterwards, cause you don't.

Second, you should use NSString's convenience methods like [NSString stringWithFormat], then you don't have to alloc an NString every time. Will save you trouble.


You have alloced imageResult in getForrrrImage and createImageFromFile and returned that for which there is no matching release. If you need to return an alloced object from a method then send it an autorelease message.

MyObject *obj = [[MyObject alloc] init];
return [obj autorelease];

Note that you can't release obj in the method as you need that object in the caller. That's why autorelease is used. You can retain the returned autoreleased obj in the caller if you need that in future.


Right now, you're returning a mess of autoreleased and retained objects, depending on the code path taken. Here's how to fix that:

First, in your createImageFromFile: you need to do return [imageResult autorelease]; and remove the [imageResult release]; from your getForrrrImage method.

Next, you have a lot of imageResult=[UIImage alloc]; which is wrong since you're allocating but not initializing the object. Also you don't autorelease it. If you don't have an image, then simply return nil instead.

Remember: you always should return autoreleased objects, except if:

  • your method starts with new
  • your method starts with alloc
  • your method contains the word copy (as in mutableCopy)

In all other cases it is expected that non-owning (i.e. autoreleased) objects are returned. While until now sticking to this was merely to make your life easier (and that of everyone who works with your code), sticking to these conventions is enforced when using the Automatic Reference Counting of iOS 5. So you want to make sure your code does follow these rules unless you love lots of debugging and refactoring later on.

I also think your use of autorelease pools is overkill and you should remove them (except if you actually debugged and measured and found that they are necessary to prevent a memory warning). Anyway, if you want to stick to them, your will need to do this to save your object from getting deallocated before you return it:

[imageResult retain];
[pool drain];
[imageResult autorelease];
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜