views:

297

answers:

2

Hi,

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!

+1  A: 

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

Nicholaz
THANKS! but I have tried this and the allocated area are still there!
Digital Robot
complementing my last comment... I verified now that the returned image is not responsible for the memory being allocated. I commented the line above //3 and replaced the last one with return nil; and instruments is still showing 1.38 MB as being allocated to CGContextDrawImage (//1)... amazing. Somehow CGContextDrawImage is not releasing the allocated area after creating the image.
Digital Robot
Yeah, it's crazy ... all you can do is write and test your code and make it the best you can and then hope that the folks at Apple also know what they're doing.
Nicholaz
(Btw, you will find other things ... e.g. that when the app ends some objects are never properly destroyed but instead that the iPhone just takes down the whole app).
Nicholaz
yes, I can see that observing what is allocated in my applications at a given time. I see stuff that I have released that are never deallocated. My problem with this example is that this is 1.38 MB... too much memory to look the other way... I will be continue seeking for an answer...
Digital Robot
A: 

apparently there's no solution for that, until Apple fix this.

Digital Robot