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 inmutableCopy
)
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];
精彩评论