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
apparently there's no solution for that, until Apple fix this.
Related
I'm currently coding my app that loads images frequently (but not the same images). As far as I test it out, there's no memory leak problem, but the memory usage of the app increases as I load up different images. It means the app will eventually gets killed by OS when it hits memory cap. I inspected through instrument and I found that a lot of memory was being held by NSConcreteData.
//from different thread, and pass data to main thread
NSData *data = [[[NSData alloc] initWithContentsOfURL:url] autorelease];
//at main, data to uiimage
imgView.image = [[[UIImage alloc] initWithData:data] autorelease];
When the view is dismissed and all allocated memories get return to heap, it seems like the memory
I allocate for NSData keep presents in the memory and therefore the memory usage of the app increases compared to what it was before it loaded images. I'm not sure if this is normal behavior.
Or is it bad practice to pass allocated memory between different threads?
This may or may not help in your exact case, but this is often reduced by paying closer attention to your autorelease stack growth. You should be able to reduce the problem by wrapping those heavy creators (data from url, image with data) in autorelease pool blocks.
#autoreleasepool { work with large NSObjects here }
or, depending on the system you must deploy for:
NSAutoreleasePool * pool = [NSAutoreleasePool new];
work with large NSObjects here
[pool release];
If you can use #autoreleasepool, do so. it's slightly better because it interfaces with the underlying autorelease stacks directly. If you need backwards compatibility, then use NSAutoreleasePool. At a higher level, they really serve the same purpose, in the sense that you should be able to interchange their implementations in your program without introducing new issues. Therefore, it really comes down to the minimum OS you are targeting and the build settings you have specified for your project when deciding which to use.
You should wrap your handling and creation of large (or many) allocations in autorelease blocks because autoreleased objects are sent release messages "at some point in the future". By creating and destroying that autorelease pool explicitly (and by using autorelease less often), you allow many of these objects to be destroyed much sooner.
As to why this can be good in addition to simply not using autorelease in your program: clients and system libraries may end up adding your big/numerous images/NSDatas to the autorelease pools. Autorelease pools are like (thread local) stacks -- when you destroy your local pool, all those autorelease messages made while your pool was on top will be fulfilled, and the autoreleased objects will receive their release messages.
Or is it bad practice to pass allocated memory between different threads?
Remember that you should message your UIKit and AppKit objects from the main thread. In Cocoa, many libraries may specify their threading models. NSData follows the Foundation threading model. The objects are not explicitly thread safe, but they are safe to use if you read and/or write from no more than one thread at any given time (that is, use a lock whenever you need to use it in a MT context, or pass copies). Passing and sharing data/objects is not a bad practice, it's necessary (or the logical solution) at times. There is a slight catch saying it's 'not bad': many people do not understand multithreading and shared resources well (it is not a trivial skill to learn for many).
Try something like this. Autorelease is less precise than explicitly releasing.
//on background thread data's retain count will now be 1
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
//on main thread (I'm assuming .image is a retained property)
UIImage *newImage = [[UIImage alloc] initWithData:data];
imgView.image = newImage;
[data release];
[newImage release];
try open Allocation to calculate memory,
and when every time you want to release something,
Make it to be nil first, make sure no one is using this variable.
Otherwise, it crash.
Make Variable equal to nil, before release.
With obj-c on the iPhone, is there any harm in autoreleasing everything instead of releasing?
Eg, this code:
NSString *recipe = [[NSString alloc] initWithUTF8String:sqlite3_column_text(dbps,0)];
[arr addObject:recipe];
[recipe release];
Can be shortened to two lines by autoreleasing the recipe nsstring when i create it:
NSString *recipe = [[[NSString alloc] initWithUTF8String:sqlite3_column_text(dbps,0)] autorelease];
[arr addObject:recipe];
Are there any drawbacks to this? I find it suits my coding style better. Thanks all.
The drawback is that the objects get released later. In most cases this won't be a problem but if you allocate and autorelease thousands of objects in a tight loop this overhead can add up to a point where it impacts performance or even causes your app to run out of memory.
In any case, you might want to use:
[NSString stringWithUTF8String:sqlite3_column_text(dbps,0)];
instead of
[[[NSString alloc] initWithUTF8String:sqlite3_column_text(dbps,0)] autorelease];
If the object does not have a scope outside the function it is used, you should always release it in order to minimize the amount of memory consumed by your application.
If you let the object stick around until the autorelease pool kicks in, a lot of unneeded memory may need to be allocated. This is especially important with iOS 4 and fast app switching, where memory is also allocated to apps in the background.
The lower your own memory footprint is, the bigger a chance there is that your application will not be terminated when in the background in case memory gets tight.
Here is my understanding on the subject, I'm sure I'll get downvoted to death if I say anything wrong ;)
Generally speaking, in tight loops, init + release will be faster than autorelease. Most of the time performance is not an issue
You may not actually want to autorelease at all times. If you want an object to stick around, you'll need to manually release or stick your autoreleased obj in a property with a retain so that you can get at it later otherwise your obj will be released as soon as it goes out of scope
With manual init + release you have more fine grained control over what is happening, this may be useful for advanced multi-threaded scenarios (especially now that GCD is pervasive)
autorelease is probably fine most of the time so long as you understand how reference counting works, but do not treat it like a silver bullet. You can still leak plenty of memory using autorelease incorrectly.
I'll turn the question around: The main disadvantage with release is that it's very easy to forget. Assignment to a local or to an instance variable look pretty much identical (they're entirely identical if you don't assign in an initializer):
Foo * a = [[Foo alloc] init];
myFoo = [[Foo alloc] init];
This, and similar issues, leads to a bunch of potential problems:
When you copy-and-paste code, will you forget a release?
When you change between local and instance variables, will you remember to add/remove the release?
If an exception is thrown, does the code leak? (This is almost always true, but it is traditional to not care about exceptions in Obj-C.)
Personally, the overhead of a memory leak when you refactor code is worse than the overhead of a few autoreleased objects. I occasionally refactor code so it looks like this:
FooView * v = [[[FooView alloc] initWithFrame:CGRectZero] autorelease];
// set up v...
myFoo = [v retain];
Local variables are marginally more efficient.
If you decide that you don't need the instance variable anymore, you just need to comment out one line.
Views are pretty heavyweight, so the autorelease overhead isn't going to matter much
For completeness, if you're doing a bunch of things in a loop (e.g. test code), you can autorelease at the end of every iteration with something like this:
for (size_t n = 100000; n--; ) {
NSAutoreleasePool * pool = [NSAutoreleasePool new];
// ... allocate and autorelease some stuff ...
[pool release]; pool = nil;
}
If you're worried about efficiency, you can gain significant speedups using (e.g.) CFString functions — the Objective-C overhead is pretty significant for small strings.
Problem is when you do autorelease you're not actually releasing the object but adding it to the current autorelease pool. Object will be effectively released when you release that pool which is done every time through the main loop .
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
You can create you're own autorelease pool but I'm not sure it would be better than simply use release.
I have an app with multiple UIView subclasses that acts as pages for a UIScrollView. UIViews are moved back and forth to provide a seamless experience to the user. Since the content of the views is rather slow to draw, it's rendered on a single shared CGBitmapContext guarded by locks by NSOperation subclasses - executed one at once in an NSOperationQueue - wrapped up in an UIImage and then used by the main thread to update the content of the views.
-(void)main {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];
if([self isCancelled]) {
return;
}
if(nil == data) {
return;
}
// Buffer is the shared instance of a CG Bitmap Context wrapper class
// data is a dictionary
CGImageRef img = [buffer imageCreateWithData:data];
UIImage * image = [[UIImage alloc]initWithCGImage:img];
CGImageRelease(img);
if([self isCancelled]) {
[image release];
return;
}
NSDictionary * result = [[NSDictionary alloc]initWithObjectsAndKeys:image,#"image",id,#"id",nil];
// target is the instance of the UIView subclass that will use
// the image
[target performSelectorOnMainThread:#selector(updateContentWithData:) withObject:result waitUntilDone:NO];
[result release];
[image release];
[pool release];
}
The updateContentWithData: of the UIView subclass performed on the main thread is just as simple
-(void)updateContentWithData:(NSDictionary *)someData {
NSDictionary * data = [someData retain];
if([[data valueForKey:#"id"]isEqualToString:[self pendingRequestId]]) {
UIImage * image = [data valueForKey:#"image"];
[self setCurrentImage:image];
[self setNeedsDisplay];
}
// If the image has not been retained, it should be released together
// with the dictionary retaining it
[data release];
}
The drawLayer:inContext: method of the subclass will just get the CGImage from the UIImage and use it to update the backing layer or part of it. No retain or release is involved in the process.
The problem is that after a while I run out of memory. The number of the UIViews is static. CGImageRef and UIImage are created, retained and released correctly (or so it seems to me). Instruments does not show any leaks, just the free memory available dip constantly, rise a few times, and then dip even lower until the application is terminated. The app cycles through about 2-300 of the aforementioned pages before that, but I would expect to have the memory usage reach a more or less stable level of used memory after a bunch of pages have been already skimmed at fast speed or, since the images are up to 3MB in size, deplete way earlier.
Any suggestion will be greatly appreciated.
I realize this is an old posting, but in case it helps anybody else .... This looks like a case of memory fragmentation. We have an app that behaves the same way. The amount of memory actually allocated by the app never reaches dangerous levels, but if you look at the amount of resident memory for the app (using VM Tracker snapshots in the Allocations Instrument, or the Activity Monitor Instrument), it climbs inexorably over time until a not-very-large transient spike kills the app.
The app in question is a multi-threaded app that makes tons of transient allocations in a large range of sizes, the timing of which can't be predicted or controlled. Such an app has to be paranoid about releasing unneeded memory allocations, not because they take up too much memory per se, but because they can create holes that prevent larger images from fitting into the allocated blocks. Even smaller allocations that tend to be overlooked are important in fragmentation (granted that the low-level allocator does group allocations by size, which is helpful to an extent). Memory zones are theoretically helpful for addressing fragmentation but pretty hard to make effective, at least in my experience. Also, use custom auto-release pools, or better yet, alloc/init as much as you can, and release as early as possible. The fact that the underlying frameworks are always making their own allocations for caching purposes probably doesn't help.
Whilst developing for the iPhone I had a stubborn memory leak that I eventually tracked down to NSXMLParser. However whilst looking for that it got me thinking about maybe changing a lot of my convenience methods to alloc/release. Is there any good reason for doing that? In a large app I can see how releasing memory yourself quickly is a better idea, but in a small app is there any other difference between the two methods.
NSNumber *numberToAdd = [NSNumber numberWithInt:intValue];
dostuff ...
OR
NSNumber *numberToAdd = [[NSNumber alloc] initWithInt:intValue];
doStuff ...
[numberToAdd release];
cheers gary.
There is no difference memory-management-wise between those two methods. In a gui app, an NSAutoreleasePool is created and destroyed on every spin of the run loop, so small objects like this will most likely be destroyed within a few microseconds. The only time I could see it mattering is if you're on a secondary thread and you're about to create a TON of autoreleased objects. However, you're always welcome to create and destroy your own autorelease pools.
[NSNumber numberWithInt:1] === [[[NSNumber alloc] initWithInt:1] autorelease]
Even though numberWithInt: is more convenient, it is more code to execute. Internally, autorelease is sticking that object onto an ever growing array.
If you are in a loop doing lots of allocations, you might benefit from managing memory yourself. In the normal course of UI operations, the cost of autorelease is negligible.
The actual definition of lots is up to you and a profiler. At what point does the benefit of more readable code lose to the benefit of faster code?
I'm trying to keep track of my sprites in an array, add and remove
them from layers, and then finally clear them out of the array.
I'm using the following code:
Sprite * Trees[50];
Layer * Forest;
Forest = [Layer node];
Forest.isTouchEnabled = YES;
[self addChild:Forest z:30];
// do this a bunch of times
Trees[0] = [[Sprite spriteWithFile:#"mytree.png"] retain];
[Trees[0] setPosition:cpv(240,160)];
[Forest addChild:Trees[0] z:5];
And then when I want to destroy a tree I use:
[Forest removeChild:Trees[0] cleanup:YES];
[Trees[0] release];
My problem is that when I look in Instruments, I'm never reclaiming
that memory, there is never a drop back down. I thought that by
releasing the sprite it would free up the memory. Am I doing this
completely wrong?
I know that when you are using the simulator with cocos2d, the memory doesn't look like it's being released, so you have to run it on the device to get an accurate picture of what's going on.
There is a good discussion here about cocos2d and memory.
What I've noticed is that everything that you create and retain must be released, but it isn't released from memory until I do this:
[[TextureMgr sharedTextureMgr] removeAllTextures];
That will release the memory.
Here's a bigger example:
Sprite * sPopup = [[Sprite spriteWithFile:#"popup.png"] retain];
sPopup.position = cpv(240,440);
[self addChild: sPopup z:2];
[sPopup release];
Then, when I'm done with sPopup in another function I have this:
[[TextureMgr sharedTextureMgr] removeAllTextures];
and the memory is freed.
My suspicion is that you are "over" retaining:
Trees[0] = [[Sprite spriteWithFile:#"mytree.png"] retain];
If Trees is a local variable in a function you do not have to retain in that case if spriteWithFile is returning a Sprite with an autorelease.
The section on delay release in the apple documentation discusses this further. The long and short of it is that the receiver of the autorelease is guaranteed to have the object be valid for the duration of its scope. If you need the object beyond the scope of the function (e.g. Trees is a property of a class) then yes, in that case you need a retain (or just synthesize a property configured to retain).
By issuing the extra retain, it is likely that your retain count is always too high (never reaches 0) and hence your object is not garbage collected.
For good measure, I'd suggest reviewing this paragraph as well that talks about the validity of objects.
Even though you call [Trees[x] release], I believe you still need to 'delete' the item from the array, like Trees[x] = nil or something, as the array itself is still containing the object.
The 'retain' in the Sprite creation is also not necessary, as [Forest addChild:z:] will place a retain on it as well (afaik).