I am reading a book which says (if I am not getting it wrong) wrapping some code with #autoreleasepool statement enables the ARC. First of all is this the case ?
My second concern is when I am doing some iOS example programs, although I enable ARC when creating a new project, I never see this directive being used anywhere (in the automatically generated code). Does this mean that ARC is not being used ? Any ideas/pointers is appreciated.
#autoreleasepool doesn't "enable" ARC. It's just the ARC way to use autorelease pools.
Before ARC, you used the NSAutoreleasePool class to set up an autorelease pool like this:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Code benefitting from a local autorelease pool.
[pool release];
But you're not allowed to call release when using ARC, so instead a new way to use autorelease pools was introduced:
#autoreleasepool {
// Code benefitting from a local autorelease pool.
}
#autoreleasepool blocks are more efficient than using an instance of NSAutoreleasePool directly; you can also use them even if you do not use ARC.
First off, the book is wrong. #autoreleasepool is orthogonal to ARC. You can use autoreleasepools without ARC and you can use ARC without autoreleasepools (but you shouldn't).
Secondly, the main thread of a project created using any of Xcode's default projects will have the autoreleasepool pool created for you. Any thread you create will need to create its own autorelease pool.
wrapping some code with #autoreleasepool statement enables the ARC
No. ARC is enabled by a compiler flag. #autoreleasepool is just a keyword used to create autorelease pools even if you're using ARC (because normally you would create and destroy them using alloc-init and release, respectively, but you can't send explicit release messages under ARC - that's why this keyword had been introduced.)
And if you enable ARC in Xcode/with the compiler/etc, it's enabled. Certainly, there are better solutions than the "autorelease everything" principle and that may be the cause of you not encountering this keyword in example code.
My second concern is when I am doing some iOS example programs, although I enable ARC when creating a new project, I never see this directive being used anywhere (in the automatically generated code). Does this mean that ARC is not being used ? Any ideas/pointers is appreciated.
You application does use this. Check out the main.m file in your project. You will find it there.
Related
I fairly new to Obj-C and am just starting out making little useless programs to help further my knowledge. I wanted to make sure I wasn't making any memory leaks. Does anything in the '#autoreleasepool' automatically release it's memory when the program ends?
Also if there are any bad habits, please let me know!
int main(int argc, const char * argv[])
{
#autoreleasepool {
Fraction* fractionOne = [[Fraction alloc]init];
Fraction* fractionTwo = [[Fraction alloc]init];
Fraction* fractionThree = [[Fraction alloc]init];
[fractionOne setTo:1 over:2];
[fractionTwo setTo:1 over:4];
[fractionThree setTo:1 over:8];
[Fraction numberOfFractions];
return 0;
}
}
See Apple's discussion of Using Autorelease Pool Blocks in the Advanced Memory Management Programming Guide.
In short, no, it is not the case that "anything in the #autoreleasepool automatically release[s] its memory when the program ends" (or at least not as a function of the #autoreleasepool). The purpose in having an autorelease pool is to control when the memory is reclaimed from autorelease items, i.e. when will the pool be drained. But your code sample doesn't appear to employ any autoreleased items, so it is not really applicable here (unless the methods used autorelease objects internally).
The most common usage of autorelease pools is to reduce the memory high-water mark of your app. See Use Local Autorelease Pool Blocks to Reduce Peak Memory Footprint. It used to be used for thread programming, but now that we have operation and dispatch blocks, we don't have to write traditional threaded code anymore, so we don't have as many occasion to need separate autorelease pools in our multithreaded code.
With ARC turned on, code is added at compile time to explicitly release fractionOne, Two and Three, so they'll get released with ARC. Without ARC, the alloc is creating a retained instance of Fraction and your code hasn't either released explicitly (almost always better) or set these as autoreleased (almost always worse).
So without arc, you're leaking during the few milliseconds this program is running.
That's more or less what it does. But don't worry: just rely on ARC. It manages your memory for you!
Using ARC, the only place you'll really see #autoreleasepool is the main function. When you start making apps, you'll write your code elsewhere and will barely ever edit the "default" main function (given to you by the Xcode templates).
So don't worry about it! Your code is fine :)
The autorelease pool object is essentially a container during runtime that holds objects (so-called autoreleased objects) alive in memory until they are released, i.e. when the pool is drained. This will happen at the end of autorelease’s scope.
Autorelease Pool is part of the Manual Reference Counting (MRC) technique in Objective-C to manage an object’s lifecycle. MRC is one of the three memory management models, the other two being Automatic Garbage Collection and ARC (Automatic Reference Counting).
During runtime, we want to avoid having memory leaks. These are blocks of allocated memory (e.g. objects) that were once alive but are not referenced by any process anymore. If we have no way of accessing or releasing them by any other running code, they can create numerous issues, e.g. cluttering and reducing the amount of available memory. The concept of the Autorelease Pool helps to mitigate this risk.
References:
NSAutoreleasePool
Programming in Objective-C, Sixth Edition (2013) by Stephen G. Kochan
I read somewhere that when we use #autoreleasepool { } blocks with ARC enabled, the compiler generates code to get the objc_autoreleasePoolPush() and objc_autoreleasePoolPop() functions called at the beginning and at the end of the block, respectively.
However, when I compile an Objective-C file with #autoreleasepool blocks, these two functions don't get called, even with -fobjc-arc. Instead, the compiler generates code to allocate a new NSAutoreleasePool object (with something equivalent to [[NSAutoreleasePool alloc] init]) at the beginning and to drain the pool (with a -drain call) at the end of the block.
So, are the objc_autoreleasePoolPush() and objc_autoreleasePoolPop() functions really supposed to be called with ARC enabled? If yes, what compiler options are missing?
objc_autoreleasePoolPush() and objc_autoreleasePoolPop() are really supposed to be called at the beginning and at the and of an #autoreleasepool block, respectively, from the code generated by the compiler, starting from OSX 10.7/ iOS 5.0. The missing compiler option is -fobjc-runtime=macosx-10.7.
And, by the way, ARC has nothing to do with all this, so that #autoreleasepool blocks make the compiler generate calls to those two functions even with ARC not enabled.
What's your deployment target set to? It may need to be OSX 10.8/iOS 6 to get the newer way of doing things.
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.
Consider the following program:
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Insert code here...
NSLog(#"Programming is Fun !");
[pool drain];
return 0;
}
I don't understand why pool is needed there as the same program can be also written as this:
int main (int argc, const char * argv[]) {
NSLog(#"Programming is Fun !");
return 0;
}
What is a purpose of using an auto release pool? Why and when do we need them? Are they mandatory in every objective C program?
If i don't want to auto release any object, do I also need to use an Auto Release pool ?
NSObject contains a neat function called autorelease. This means all objects in Objective-C contain this function.
This function inserts self into the autorelease pool, delaying the call to object's release function until the autorelease pool is deallocated. Most internal APIs use an autorelease pool, and beside the one located in main(), there is one allocated and deallocated in UIKit's main loop in every pass.
In short: it's the queue for delayed decrement of reference counter.
Example on where autorelease is hidden:
[NSString stringWithUTF8String:"some string"];
This object is allocated, and autorelease is called on it. How would you use it yourself?
MyObject *obj = [[[MyClass alloc] init] autorelease];
Why is this good? When you return this object, the calling function does not need to take care to release this object, and optionally it can retain it (but doesn't have to).
To expand and clarify four years later:
While UIKit and AppKit create and drain an NSAutoreleasePool during the course of their main runloop, in your non-GUI program you need to create it yourself. Various code expects having an NSAutoreleasePool present, and since you didn't initialize a GUI framework nor you use one, there is no code that will magically create it for you.
While NSLog() and a constant NSString in your example don't require a pool, even the trivial [NSMutableArray array] does, given that it can actually be interpreted as [[[NSMutableArray alloc] init] autorelease].
But if i don't want to auto release any object, then also do i need to use Auto Release pool ??
Also note that the Cocoa library uses autorelease extensively. So, even if you think you don't use the pool in your code, you need to prepare the pool.
I have found reason...
"If a pool is not available, autoreleased objects do not get released and you leak memory. In this situation, your program will typically log suitable warning messages."
You typically do not have to create an autorelease pool block yourself, or even see the code that is used to create one. three occasions when you might use your own autorelease pool blocks,
If you are writing a program that is not based on a UI framework,
such as a command-line tool.
If you write a loop that creates many temporary objects - You may use
an autorelease pool block inside the loop to dispose of those objects
before the next iteration. Using an autorelease pool block in the
loop helps to reduce the maximum memory footprint of the application.
If you spawn a secondary thread - You must create your own
autorelease pool block as soon as the thread begins executing;
otherwise, your application will leak objects.
A general introduction can be found on Apple's website:
Autorelease Pools and Ownership and Disposal
Check out the NSAutoreleasePool documentation