Objective-C Memory Management: Am I understanding this? - objective-c

I've finally decided to stop beating around the bush and teach myself some Objective-C. It's all making sense, except when I get to the memory management and this idea of the "autorelease pool".
From my understanding, if I specifically create an object using init,new, alloc or tell it to retain, then it is my job to deallocate the memory. However, an autorelease pool will automatically free up any objects associated with the innermost autorelease pool?
For example, say I do this:
TestOBJ* foo = [[[TestOBJ alloc] innit] autorelease];
Then it will be released at the end of the first #autoreleasepool block, or whenever the first [autoreleasepool drain] is called?
Also; just because an object is created within an autoreleasepool block doesn't mean it is automatically labeled as autorelease, correct?

Correct for both points.
Objects only get added to autorelease pools if you call -autorelease on them. By convention all methods not starting with alloc, new, copy or mutableCopy return objects that they have themselves added to the autorelease pool, so you don't have to do it yourself.
See http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html for details.

You pretty much answered all your questions yourself correctly.

Related

Is AutoRelease redundant when using ARC in Objective-C?

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.

Do autorelease pools have their own memory slabs to achieve fast deallocation?

People say that autorelease pools free up autoreleased objects quickly. But there are two kinds of autoreleased objects:
Those that are autoreleased after init e.g. [[[NSString alloc] init] autorelease]
Those that are autoreleased during creation e.g. NSString stringWithFormat.
It seems to me that if Apple wanted to get the best performance, it would put the latter into a slab. However doing the same for the former is impossible, if an id is a memory pointer rather than an actual id.
At any rate, do autorelease pools have their own memory slabs to achieve fast deallocation of some objects?
One can't tell this exactly (only an Apple engineer who will be fired after leaking this info), but if you look at alternative solutions/implementations of Foundation, for example, GNUstep, you'll see that "second-type" autoreleased objects are created in a way like:
+ (NSString *) stringWithString:(NSString *)otherString
{
return [[[self alloc] initWithString:otherString] autorelease];
}
However, autorelease pools still can implement their own methods to fast deallocate objects. You can, one more time, have look at GNUstep's NSAutoreleasePool.m in order to find out what it exactly does.
It also seems to me that you're not sure whether id is or is not a pointer. It is.
Conveniently, this is open source! Check out http://www.opensource.apple.com/source/objc4/objc4-493.9/, specifically objc-arr.mm (for things like _objc_rootAlloc, which is what +alloc goes through), and from there you can see the following comment:
/* Autorelease pool implementation
A thread's autorelease pool is a stack of pointers.
Each pointer is either an object to release, or POOL_SENTINEL which is
an autorelease pool boundary.
A pool token is a pointer to the POOL_SENTINEL for that pool. When
the pool is popped, every object hotter than the sentinel is released.
The stack is divided into a doubly-linked list of pages. Pages are added
and deleted as necessary.
Thread-local storage points to the hot page, where newly autoreleased
objects are stored.
*/
To directly answer your question though, no, no tricks like that are done. Autorelease pools merely manage pointers efficiently, not object storage.

Using autoReleased objects without an NSAutoReleasePool?

I'm writing my very first steps in Objective-C.
I followed some examples and the official documentation, and am using autoreleased objects* without explicitly declaring an NSAutoReleasePool.
* By autoreleased objects I mean: SomeClass *obj = [SomeClass someClass];
Is it ok to do it this way?
Will it cause a memory problem?
Is declaring a NSAutoReleasePool more efficient?
edit: I made a mistake in the code example, what I meant was getting an object by it's class factory method instead of allocing an instance of it. This factory methods [often|always] return autoreleased objects, right? for example: [NSString stringWithCString:x]
You don't need to create an autorelease pool explicitly usually. When you do normal Mac programming using the AppKit framework, there will be an implicit autorelease pool which is handled by the event loop. You need to concern yourself with autorelease pools mainly on two occasions:
Your code runs in a background thread: If you have a background thread there is no autorelease pool created for you and you will have to do this manually.
You have a tight loop where you create and destroy a lot of objects. If in this loop any objects are autoreleased they will not actually be released until the autorelease pool is drained. This means that your memory consumption will rise, even though you don't reference those objects anymore. In this situation having a local autorelease pool can help with performance, although switching from autoreleasing to explicit retain/release is probably more efficient.
In answer to your question: that's a no-no. You will leak memory if you autorelease an object (or use an autoreleased object) in a scope that has no autorelease pool.
perhaps ignore the following:
With regard to your example, it might be rather confusing the way you've written it, since Class is a typedef of struct objc_class*. So, you're really declaring a pointer-to-a-pointer to a class, and then assigning a pointer to a class to it. Which won't work. Moreover, since Class is not an Objective-C “class-type” per se, you can't send messages to it.
But all this is neither here nor there, since ±class does not return an autoreleased object.

Autoreleasing in Objective-C application when returning a value

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.

What is the difference between releasing and autoreleasing?

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.