I still have some unclear understand about release and autorelease. What are the difference between both of them? I have this code. For facebook connection. I crash it sometimes when I go to Facebook login, I doubting maybe it is because I don't release the object nicely.? Thanks for any helps
if (_session.isConnected) {
[_session logout];
} else {
FBLoginDialog* dialog = [[[FBLoginDialog alloc] initWithSession:_session] autorelease];
[dialog show];
}
The Memory Management Programming Guide for Cocoa will soon be your best friend. In brief, object instances in Cocoa are memory managed using reference counting (unless, of course you're using garbage collection on OS X). An object indicates that it wants to 'retain' an ownership interest in an other instance--keep it from being deallocated--by sending it a -retain message. An object indicates that it wants to release that interest by sending the other instance a -release message. If the number of objects that have 'retained' and ownership interest in an object drops to 0 (i.e. when the last of the owning instances sends a -release message), the instance with a 0 retain count is deallocated.
It's sometimes convenient to say "I want this instance to be released some time in the future". That's the purpose of -autorelease. Sending an -autorelease message adds the receiver to the current NSAutoreleasePool. When that pool is drained, it sends a -release message to all the instances in the pool. An NSAutoreleasePool is automatically created at the start of each iteration of each thread's run loop and drained at the end of that iteration. Thus, you can do something like this in a method:
- (id)myMethod {
return [[[MyObject alloc] init] autorelease];
}
The caller of this method will get back an instance that they can -retain if they wish to keep it. If they don't retain it, it will stick around at least until the enclosing autorelease pool is drained:
- (void)someOtherMethod {
...
id instance = [obj myMethod];
... // do more with instance, knowing that it won't be dealloc'd until after someOtherMethod returns
}
Releasing means you release that right away.
Autoreleasing means you want the variable to be released on the next autorelease pool.
You use autorelease when you want to keep retaining the variable but don't want to create a memory leak. You use release when you don't need the variable anymore.
Sample:
- (NSNumber *)return5 {
NSNumber * result = [[NSNumber alloc]initWitnInt: 5];
[result autorelease];
return result;
}
Why do we use autorelease there?
If we use [result release] instead, variable result will be destroyed AT that time. Which means that the returned value will be garbage.
If we do not release at all, variable result will be hold FOREVER incurring memory leak.
We can tell every caller to the function to release result but that would be a headache and prone to error.
So we use autorelease. We mark the variable to be released on the next autorelease pool. Basically we mark the variable to be released near the alloc. Hence the mantra alloc is paired with release in the same function holds all the time.
Actually, you'll do fine changing all release into autorelease. Your memory use won't be efficient, however, the effect is minimal. All variables, in all programming language is effectively autoreleased.
Anyway, use ARC.
background discussion:
objective-c is reference counted, so objects are deleted when the reference count reaches 0. release reduces the reference-count immediately, autorelease reduces it when the autorelease-pool is popped
when to use:
use autorelease when allocating the object if
you do not need it after the current function
it will be retiained by some other objet/function and will be released by a later by the retaining code
when the logic of the current function is tricky, so you would have to send release in a dozen different places before doing a return
use "manual" release
to revert a previous retain (in case you are implementing a library)
if you need precise control of freeing objects (e.g. they use lots of memory or the autorelease pool will not be popped for some time)
but really my freand:
read the Memory Management Programming Guide for Cocoa as suggested by Barry and run your code with instruments (zombies and leaks) often to catch any and almost all memory management errors.
Erik
According to the Memory Management Programming Guide for Cocoa:
The autorelease method, defined by
NSObject, marks the receiver for later
release. By autoreleasing an
object—that is, by sending it an
autorelease message—you declare that
you don't want to own the object
beyond the scope in which you sent
autorelease.
Also:
The autorelease method thus allows
every object to use other objects
without worrying about disposing of
them.
Related
I'm new to Objective-C and cocoa. In the guide provided by Apple for Cocoa, there is a confusing example in memory management:
Suppose you want to implement a method to reset the counter. You have a couple of choices. The first implementation creates the NSNumber instance with alloc, so you balance that with a release.
- (void)reset {
NSNumber *zero = [[NSNumber alloc] initWithInteger:0];
[self setCount:zero];
[zero release];
}
The second uses a convenience constructor to create a new NSNumber object. There is therefore no need for retain or release messages
- (void)reset {
NSNumber *zero = [NSNumber numberWithInteger:0];
[self setCount:zero];
}
I am not sure why the object is created with 'new' instead of 'alloc & init' does not need to be retained/released. My understanding is that both are doing the same thing, except that with 'alloc & init' we can use custom checks and initialisation.
Many thanks.
The second example returns an auto released object. The code for the convenience constructor probably looks like this, at least when it comes to replicate the functionality.
+ (NSNumber *)numberWithInteger:(NSInteger)integer
{
NSNumber *number = [[NSNumber alloc] initWithInteger:integer];
return [number autorelease];
}
Autorelease is a way to defer sending a release method to an object while not delegating ownership of the object to the caller of the constructor. This is an important concept, because the naming conventions require you to not return ownership of an object unless your method starts with copy new alloc or retain. However, since you can't return an owned object, you would have to call release on it in your convenience constructor, which would then lead to you returning a deallocated object. So, autorelease allows you to return an un-owned object to the caller which will receive an actual release method later (when the current autorelease pool gets drained).
Autorelease methods are collected in so called autorelease pools, which are thread local quasi linked lists (they are not implemented as linked lists, but they do work like they were) and that just collect autoreleased objects. Objects can be added to them multiple times by calling, once for each autorelease method they receive. When the pools is drained or destroyed, all objects it contains will receive a release message. By default, the system will provide you with an auto release pool, at least on the main thread, but you can create your own ones using this code (which is also used in every main method, if you take a look):
#autoreleaspool
{
[foo autorelease]; // foo will receive a `release` method at the closing brace
}
By convention, all methods who's name start with "alloc" or "copy" or "new" increase the retain count by 1.
All other methods do not change the retain count. Since "numberWithInteger" doesn't start with "alloc" or "copy" or "new" it returns an object with a retain count of 0. But instead of setting it to 0 immediately (which would never work), it sets the retain count to 1 and then schedules it to be dropped down to 0 at some point in the future (usually when the event loop is idle, but you can manually make it happen sooner), using an "autorelease pool".
The only exception to the alloc/copy/new naming convention is, of course, the actual "retain" and "release" and "autorelease" methods, which increase/decrease the retain count or schedule it to be decreased later.
It is not a language feature, it's just a coding practice. Every method starting with "alloc" and "copy" and "new" sets retain to 1, everything else sets it to 1 but schedules it to be dropped to 0 later.
Of course, if you are using ARC, and you should absolutely be using ARC, then you don't have to worry about any of this because the compiler will find the last line of code that uses the object, and will insert a line of code after it to free up the memory. This leads to faster code, because the autorelease mechanism is a bit slow and sometimes uses too much RAM.
When ARC is enabled, none of those rules apply. The compiler ignores all your memory management code (or tells you to delete it), and writes it's own code. It's not actual garbage collection, it's just manual memory management that is generated by Xcode instead of written by hand.
Objects that are created with +alloc -init are returned with a retain count of +1, meaning that you have to call -release when you are done with this object. This is the same with +new , which is just a simple combination of [[ alloc] init], eg.
NSDate *date = [NSDate new]; // I will have to send -release at some point
As a convention, methods that contains init, new, create and copy will transfer ownership to you, meaning that you need to send -release at some point. Other methods will not transfer ownership, meaning that the object is autoreleased, ie. it has a short lifetime and is scheduled to be dealloced in the future. If you want this object to stick around, you will need to explicitly take ownership by sending -retain.
NSDate *date = [NSDate date]; // I won't have to send -release
// But this object will be dealloced soon
// so if I want it to stick around, I will need to retain it
This convention is not enforced by the language.
It is also useful to remember that this convention expands beyond the Objective-C part of the SDK, it is also the case in CoreGraphics and all C frameworks provided by Apple, and most third-party frameworks make use of this convention.
CGContextRef context = UIGraphicsGetCurrentContext(); // I won't have to release this context
CGImageRef result = CGBitmapContextCreateImage(context); // I will have to release this image
/* ... */
CGRelease(result);
As for your example : -numberWithInteger: does not contain either init, new, create or copy. So you don't need to -release it when done.
I am not clear about how to use autorelease;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
RetainTracker* tracker = [RetainTracker new];
[tracker retain];
[tracker retain];
[tracker autorelease];
[pool release];
Is there any memory leak in the above code?
I know the autorelease just puts tracker into NSAutoreleasePool, without modifying the reference count for tracker. When i call [pool release], the object receives one message release, then the reference count of tracker is 2. So the compiler can't call the dealloc function of object tracker, so there is a memory leak.
So i get this: we shoul call retain and release same times, is it right?
If you're new to Objective-c, you should be using Automatic Reference Counting. Almost everyone should. But for the sake of understanding:
An object has a reference count of how many objects have a reference to it. When it drops to zero, the object is not referenced by anything and is deallocated. Every method in Objective-C is responsible for releasing any object it retains. The problem is, if a factory method's job is to create an object, it's breaking the rules by not releasing an object it retained (in this example it was retained because it was created). If the method called release on the object right before returning it, it would be returning the address to an object that is already gone. So, there is autorelease, which temporarily delays the release until the calling method can retain the object the called method created.
In your example above, if you got rid of the 2 retains, and only called autorelease, then the object would get released and deallocated when the autorelease pool is released and (right before deallocation) is drained, meaning it calls release on all objects in its pool, tracker being one of them because calling autorelease on tracker added it to the pool.
new is equivalent to doing an "alloc" & "init", so retain count on tracker on that line is 1.
Then you increment the retain count 2 more times to give a total retain count of 3.
Autorelease sets the tracker to be released when the pool is released (and the retain count is decremented as well). But it's already retained 3 times, so it doesn't really get released.
And yeah, there is a memory leak with the retain count being greater than 0 and no reference to "tracker" outside of that method (that is, unless you're using "tracker" in an instance variable).
It's very good to know the basics of memory management; but if you want to save yourself a ton of headache, just do what everyone else here seems to be saying and simply enable ARC.
EDIT: And to finish your question, you should make sure every call to retain is balanced with a release. You also do a "new", which also increments the retain count so you need to "release" because of that as well.
I'm pretty new to Objective-C, as you may gather, and until recently, I hadn't really understood the need for all this AutoRelease malarky. I think that's mostly because I've started Objective-C with ARC, and haven't had any exposure to doing retains and release.
Anyway, my understanding now is that pre-ARC, if you created an object and needed to return a pointer to it as the returning object of the method/function, you would need to autorelease it, because you are unable to do the "[obj release]" after doing "return obj;"
Worrying about retains and releases isn't an issue with ARC. Does this mean that in our own code, there is really point in creating our own autoreleased objects? Ie, doing [[[Class alloc] init] autorelease]? From what I've gathered, we should still setup autorelease pools, but only because other frameworks or libraries may still return autoreleased objects, but we no longer need to explicitly create autoreleased objects ourselves - is this a fair understanding?
Thanks,
Nick
When using ARC, you do not want to do any memory management yourself. Specifically you will not be calling release and auto release because it does it all for you. In fact, the compiler should probably complain if you try to manage memory yourself.
Instead of [[[Class alloc] init] autorelease]; you'll just call [[Class alloc] init];
I recommend reading this blog post for some really good background on ARC and memory management in general.
Well, your understanding is quite correct. With ARC we do not release or autorelease any more. Just have to make sure that we assign nil (or some other reasonable value) to any reference to objects, which we do not need any more. In the worst case we could still constantly consume additional memory but the memory cannot leak any ore.
And yes, we still maintain autorelease pools for the sake of using framework libraries (linked ones) that may not use ARC.
To answer your question between the lines about the purpose of autorelease. This applies to non-ARC project only, of course.
In the good old days Objective-C did not offer any reference counting but its retain counting. Any allocated memory of objects, that are not retained (or have a retain count of 0) is considered free and may soon be claimed and used by other objects.
This means that every object needs to be retained after its allocation, assuming that you want to keep it around. When the object is not used any more then you need to release it. This comes with two risks. Well, alloc does retain it once automatically.
1) You may forget to release an object that is unused. In the worst case you may even loose all references to an object that stays in memory for ever since.
2) You may still refer to an object hat has been released already and then try accessing it which will most likely end in an BAD_EXC exception.
All this can be quite annoying. In order to get rid of some of these obligations for objects that don't stay around very long, the autorelease was invented. For temporary objects only you alloc it (release-count = 1) and autorelease it. That means that the object will be automatically released (retain count reduced by 1) within the next autorelease circle. But the object remains allocated for your method while it is being executed. Typically the reference variable would be a local one.
Sample:
-(void) myMethod{
AClass *someObject = [[[AClass alloc] init] autorelease];
// use the object
// probably hand it to another object if that takes ownership, i.e. add it ot an Array using addObject:
// don't care any more
}
And that not required any more when using ARC.
I've read apple documentation to assert that I was doing the memory management correctly but some questions raised.
Question 1:
They exhibit this code snippet as wrong :
in obj implementation:
- (NSString *)method1 {
NSString *string = [[NSString alloc] initWithFormat:#"%# %#", firstName, lastName];
return string;
}
... later ...
NString* myString = [obj method1];
NSLog("%#", myString);
[myString release];
Apple Doc :
You own the string returned by alloc, but lose the reference to it before you get a chance to relinquish ownership. Following the memory management rules, this would result in a memory leak, since the caller has no indication that they own the returned object.
Since I'm taking care of releasing the object that has been allocated previously, there is no memory leak, right ? What do they mean by "lose the reference to it" ?
It is wrong only regarding apple's memory management recommendations (the caller has no indication that they own the returned object) or this is also technically wrong ?
Question 2 :
This is about autoreleased objects availability :
Example code:
in obj1 implementation:
- (NSString *)methodA {
NSString *string = [[NSString alloc] initWithFormat:#"%# %#", firstName, lastName];
return [string autorelease];
}
in obj2 implementation:
- (NSString *)methodB:(NSString *)inputString {
NSLog("%#",inputString)
//*other call of methods with arg inputString*//
}
... later ...
NString* myString = [obj1 methodA];
[obj2 method2:myString];
How far (or deep) following my functions calls will the autorelease object returned by obj1 will be available. Regarding apple's documentations "Autorelease objects will be available within their variable scope". Should I retain it at some point ?
Q1: It is wrong only regarding apple's memory management recommendations (the caller has no indication that they own the returned object) or this is also technically wrong ?
Technically this is correct as you release myString after using it. However if you follow Apples guidelines for method naming (strongly recommended), this is clearly wrong:
You own any object you create.
You “create” an object using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy).
method1 doesn't contain create, alloc, new or copy - thus per the guideline the caller doesn't own the object and doesn't have to release it.
Q2: How far (or deep) following my functions calls will the autorelease object returned by obj1 will be available. Regarding apple's documentations "Autorelease objects will be available within their variable scope". Should I retain it at some point ?
Auto-released objects will be alive until the closest Autorelease Pool is drained, see Autorelease Pools:
An autorelease pool is an instance of NSAutoreleasePool that “contains” other objects that have received an autorelease message; when the autorelease pool is deallocated it sends a release message to each of those objects. An object can be put into an autorelease pool several times, and receives a release message for each time it was put into the pool. Thus, sending autorelease instead of release to an object extends the lifetime of that object at least until the pool itself is released (the object may survive longer if it is retained in the interim).
...
The Application Kit automatically creates a pool at the beginning of an event cycle (or event-loop iteration), such as a mouse down event, and releases it at the end, so your code normally does not have to worry about them. There are three cases, though, where you might use your own autorelease pools:
...
So, if you need your instances to stay alive after the corresponding autorelease pool was drained, take ownership by retaining them. Otherwise you usually just let them be handled by the pool.
Since I'm taking care of releasing the object that has been allocated previously, there is no memory leak, right ?
right
What do they mean by "lose the reference to it" ?
you hold no pointers for the object, such that the object may not be accessed in your program.
It is wrong only regarding apple's memory management recommendations (the caller has no indication that they own the returned object) or this is also technically wrong ?
also correct. the static analyzer will prolly cry too
How far (or deep) following my functions calls will the autorelease object returned by obj1 will be available. Regarding apple's documentations "Autorelease objects will be available within their variable scope". Should I retain it at some point ?
this is a little more complex. autorelease pools are stacked upon each other by thread. that's why you must create one when entering a thread or new event loop iteration, and also why it is a good idea to create them explicitly when performing large operations which create many (autoreleased) allocations.
finally the last pool in the stack (for the thread) is destroyed at the end of the run loop's iteration.
if the object is created under an autorelease pool you create explicitly, then you must retain it to use it beyond the lifetime of the pool which it was created in.
similarly, you must formally retain/copy when passing to other threads. typically, this happens immediately - you just create a copy or retain the formal arguments when entering the implementation of the secondary thread.
I read the memory management guide for the Objective-C language, but this is a doubt I still have, even after reading many times the chapter.
Let's say I want to return an object I just created in a method of an object like this:
NSString* ret = [[NSString alloc] initWithString:#"My string"];
return ret;
I can do this, but it is not correct according to the ownership policy. The guide states that the correct solution would be to:
NSString* ret = [[NSString alloc] initWithString:#"My string"];
return [ret autorelease];
because, as I'm autoreleasing, I'm no more the owner.
My question is: when will the NSString be actually released and deallocated? When the last initialized pool is released? This means that, if I don't create a pool, this object will be released when the application is closed (the pool that xcode creates by default is released at the end). Is this correct?
The same applies to objects which are not allocated by me like:
NSString* ret = [NSString stringWithString:#"My string"];
? If I don't create a pool to release it elsewhere, it is released at the end of the application when the pool created by xcode is released?
Thanks for any clarification.
When you call autorelease, you're handing your ownership to the nearest autorelease pool, to be released at the next drain.
There must always be an outermost autorelease pool, but usually there will be other ones closer to the action. You don't have to create these explicitly -- though you can do that too -- they are created by the Cocoa framework in the course of going about the program's business.
If you're coding a non-GUI tool that never hands off to the framework, and you never create another pool, and never call drain on the existing one, then the object will be released when the pool itself is, just before exiting. Otherwise, it will most commonly be released at the end of the event handling cycle, which is one of the key places the framework maintains a pool.
In general, the case of objects created via convenience class methods is the same as those alloced and autoreleased. As it happens, the one you cite from NSString would be a little different because at its base is a constant string, and that doesn't get managed quite the same way. But that's an implementation detail.
Objects go into the current autorelease pool when they're autoreleased. When the pool itself is sent release (or drain, which is the same thing), the objects in it are also sent release. As for when the current autorelease pool will be created and released in most cases, the memory management guide chapter on autorelease says:
The Application Kit automatically creates a pool at the beginning of an event cycle (or event-loop iteration), such as a mouse down event, and releases it at the end
So in practice, autoreleased objects will go away very quickly — before the end of the app's lifetime, and in fact before the next touch/mouseMoved event message is sent.
It's possible to create your own local autorelease pool to make them go away even more immediately if you need to, but that's normally a micro-optimization that might actually make things go a bit slower (it increases the number of messages being sent without necessarily making anything else take less time).
Keep in mind that -autorelease is nothing but a delayed messaging facility. When you send -autorelease to an object, the current autorelease pool will add that object to its list, and when the pool is drained or released, it will send a -release message to every object in its list.