Normally when you create an NSOperation subclass you are responsible for creating and releasing an NSAutoreleasePool in the -main method.
When you use an NSBlockOperation, do you need to create an autorelease pool in the block?
No. GCD (which NSOperationQueue is built on top of as of OS X 10.6 or iOS 4.2) manages autorelease pools for you, the same way that NSRunLoop does.
I don’t think so, as the work queues have their own pools already created for you.
Adam,
Your best bet is to read up on block memory behavior with objects. Here is the link for the iOS Blocks and Variables the bottom of this page has information regarding object types.
Frank
Related
I'm quite new to the Objectivce-C and I was wondering what is the correct way of memory management in a static library without ARC.
Lets say my library has a method that returns NSString*:
- (NSString *) foo
{
...
NSString *result = [[NSString alloc] initWithString:#"bar"];
return [result autorelease];
}
So as far as I understand, since foo allocated the NSString it also needs to release it (or queue it for releasing). NSString is a return value, so the only thing I can do is to autorelease it. This creates a problem: if library is used in a command line tool, the developer needs to know that foo needs an #autoreleasepool otherwise calling foo multiple times inside main #autoreleasepool with eat up memory. This seems to me like I'm delegating memory management from library to the app which seems like a terrible thing to do. Is there a better way to do this? Or can I somehow make it obvious for the developer that foo needs an #autoreleasepool?
Autorelease pools do not deallocate objects automatically; they need to be manually drained. In Cocoa applications, this is done by the main thread's run loop, so normally most of developers don't have to do anything for that and don't know about it.
However, in any long-running functions, like command-line tool's main, or a background thread, it's the programmer's responsibility to manually drain autorelease pool periodically.
You are following the global memory management rules and that's the right thing to do. There's no need to change anything; it's not about ARC or static libraries.
Every thread requires an autoreleasepool*. If your code is called and there is no pool in place then the thread hasn't been set up properly and this is a programmer error.
Unless you created the thread (or process) this isn't your responsibility and has nothing to do with lazy memory management on your behalf.
The reason methods don't indicate that they need an autoreleasepool to be in place is because an autorelease pool always has to be in place.
*Sure you can write Objective-c that doesn't use autorelease, and about which you can reason with almost certainty will never use autorelease when internals change. Such code would only be able to use a small subset of Cocoa, if any, and would likely be pretty terrible.
According to this Apple page, I've read that when interacting with Cocoa on a POSIX thread that I should create a NSAutoreleasePool.
If you are making Cocoa calls outside of the Application Kit’s main
thread—for example if you create a Foundation-only application or if
you detach a thread—you need to create your own autorelease pool.
Unfortunately, using NSAutoreleasePool is disallowed in ARC.
What should I do then to guarantee that there is always an pool available for any ARC code that is autoreleased?
Thanks!
Use #autoreleasepool.
#autoreleasepool
{
// make Cocoa calls here
}
This allows the compiler to reason properly about the lifetime of objects that cross the pool's boundary, which is a requirement for ARC. (That's why you can't use NSAutoreleasePool.) As a bonus, it's also faster.
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.
Just wondering if this is even possible, maybe I could retrieve an NSSet of objects that are currently stored in a given NSAutoreleasePool instance?
I have looked through Apple's NSAutoreleasePool reference and have not found much pertaining to this question.
If the purpose is just for debugging, you could use the function _CFAutoreleasePoolPrintPools() to print the content of the pool, as documented in TN2124. It is available since Mac OS X 10.6 and iOS maybe since 3.x.
Alternatively, the class method [NSAutoreleasePool showPools] performs the same action.
No, there is not. The implementation details of NSAutoreleasePool are deep black magic.
What you might do instead is to make your own autorelease pool and somehow fool the runtime into thinking that it should use your pool instead of NSAutoreleasePool. But only do this for the thrill of trying it.
HOWEVER, YOU SHOULD NEVER ALTER AUTORELEASE BEHAVIOR FOR ANYTHING OTHER THAN EXPERIMENTATION AND LEARNING. OTHERWISE I WILL FIND YOU. AND MAKE YOU REWRITE YOUR CODE.
I created an NSOperation. Do I also need to create an autorelease pool for this or is it all handled for me like voodoo black magic?
The NSOperation may run on any thread, so yes, you must set up your own autorelease pool for the work being done.
You do need to create autorelease pool yourself in the NSOperation main method, if the environment doesn't support automatic garbage collection.