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.
Related
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.
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 have audio class that sample the buffer and with NSNotification it calls another class and send a data(int).
I get this warning that runs many many times a second:
class __NSCFNumber autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool()
class __NSCFString autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug
what does it means?
yes I have NSNumber in that class and NSString.
they are not allocated.
do I need another thread?
what's wrong?
It means that, for whatever thread that code is running on, no autorelease pool has been set up before that code runs. For AppKit- or UIKit-based apps, the framework normally managed one for you on the main thread, but you'll still need to create them yourself if you're using other threads. For apps that are not based on AppKit or UIKit, you'll pretty much always need to make sure there's an autorelease pool around when you're running Objective-C code.
Do you use an autorelease pool in your main() function in the application? Do you use the autoreleased instances (yes, I know, you didn't alloc-init them, but [NSNumber numberWith...] returns an alloc-init-autoreleased object) in a thread other than the main thread? If you haven't initially set up an autorelease pool, or you're using multiple threads, you must create an individual NSAutoreleasePool for each thread.
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.
Does autorelease guaranty that at the end of blocks the object will get released?
Or is it better to manually release objects?
It guarantees it will be released sometime after the block executes, not necessarily immediately after. It's up to the runtime to determine exactly when.
It's not big deal unless you're doing something with a lot of autoreleased variables, like creating them in a big loop, or if you're creating large autoreleased objects, like UIImages. In these cases, you should manually release when you're through, otherwise autorelease is perfectly acceptable.
If an object is autoreleased, you MUST not manually release it (unless it is retained of course). The NSAutoRelease pool which is part of the UIKit event handler will release it for you. If you were to manually release the object, the pool may cause a crash or other undefined behavior as the object will be doubly-released.
If there are cases where you generate a lot of objects or use a lot of memory in objects, you can pre-emptively autorelease them (perhaps in your loop) by creating your own NSAutoReleasePool - pools can be nested.
It's better to release objects rather than autorelease, unless of course you have an explicit reason to use autorelease, for example use autorelease when returning an object the method retained and you can't avoid it.
Basically autorelease should be used as an excuse to completely avoid memory management. You want to release objects as soon as you possible can. Autorelease just says the object will be released some time in the future.