简体   繁体   中英

IPHONE: memory still allocated after releasing object?

I have a method for drawing an object offscreen to a file, using quartz. The last lines of this method are:

CGRect LayerRect = CGRectMake(mX,mY, wLayer, hLayer);
CGContextDrawImage(objectContext, LayerRect, objectProxy.image.CGImage); // 1

CGRect superRect = CGRectMake(vX, vY, w,h);
CGContextDrawLayerInRect(context, superRect, objectLayer);

CGLayerRelease(objectLayer); // 2
UIImage * myImage = UIGraphicsGetImageFromCurrentImageContext();  
UIGraphicsEndImageContext(); //3
return myImage;

as You see the layer drawn on //1 is released on //2, and the context is released on //3.

So, there's no leak right?

In fact, instruments reports this as having NO LEAKS, but after running this method and returning to the main loop, my application is using 1.38 MB of memory more than before.

Investigating on intruments, on memory allocation tab, I see an entry as

Malloc 1.38 MB
overall bytes = 1.38 MB
#Overall = 1
#alloc = 
Live Bytes = 1.38 MB
#Living = 1
#Transitory = 0

and this entry points to this

CGContextDrawImage(objectContext, LayerRect, objectProxy.image.CGImage); // 1

So, apparently the memory allocated inside the method is still allocated but is not leaking?? How can that be?

How can I get rid of this memory allocation freeing the memory?

thanks in advance!

The image would certainly use some memory. I'm not totally proficient with iPhone programming but an image under OS X is always a copy of what you made the image from. The docs say that the image lives in an autoreleasepool, so depending on how you manage the pools, it could live there for quite some time. You could try putting an autoreleasepool around the call in the calling function (putting it into te function you're quoting above would return an invalid object).

Generally I can say that as soon as autoreleasepools are coming into play, trying to track the releasing of objects will become quite cumbersome (and impossible sometimes ... the idea behind autorelease objects is that the system knows best when to release them (which is something that drives a C++ programmer like me nuts ... but of course Objective C and Cocoa is not made to make me happy :-)))

However, assuming your function above is called drawOffline you should be able to get rid of the memory in image via

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
UIImage *ret= [self drawOffline];
// do some work using ret (possibly copying it)
[pool release];
// memory should be released and the ret ptr is invalid from this point on.

going a bit further, if you intend to use the ret ptr a bit longer you should retain it to tell the system that it should not delete it even if the autorelease pool releases it.

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
UIImage *ret= [self drawOffline];
[ret retain]; // prevent ret from being deleted when the pool releases it
// do some work using ret (possibly copying it)
[pool release];
// ret ptr will continue to live until you release it.

// more stuff

[ret release]; // image behind ret being freed 

As said, generally with autorelease objects you don`t worry about their lifetime, but if you intend to keep them longer (especially storing it in an object member for later use) you need to retain/release it yourself, because otherwise the system could pull it right under your feet.

This [link][1] describes memory management under OS X but also applies to the iphone.

[1]: http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html link

在苹果公司修复此问题之前,显然没有解决方案。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM