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
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'm learning objective-c and would like to clarify a thing:
when I use autoreleasepool should I send an autorelease message after using test object?
for (int i = 0; i < 10; ++i)
{
#autoreleasepool {
TestClass* tc1 = [[TestClass alloc] init];
//....... do some stuff with tc1
[tc1 autorelease];
}
}
when I use autoreleasepool should I send an autorelease message after using test object
They don't have any correlation whatsoever.
What you should do depends on what you want to do and whether or not you're using automatic reference counting.
If you're using ARC (which I think is not the case, since you send an autorelease message), then you don't have to worry about releasing objects at all in simple cases. (If you have to use advanced memory management with more complicated models, then ARC is even more complex than MRC, but anyway...)
If you're not using ARC, there are two options. autorelease lets an object be released at the end of the innermost-scoped autorelease pool. So in the example you provided, it's OK to do this.
However, autoreleasing is primarily intended to dispose of ownership when returning objects from a method/function, and in general, you want to explicitly send a release message to an allocated-initialized object when you no longer need it.
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.
I have a problem with the memory management in Objective-C. Say I have a method that allocates an object and stores the reference to this object as a member of the class. If I run through the same function a second time, I need to release this first object before creating a new one to replace it. Supposing that the first line of the function is:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
This means that a different auto-release pool will be in place. The code to allocate the object is as follows:
if (m_object != nil)
[m_object release];
m_object = [[MyClass alloc] init];
[m_object retain];
The problem is that the program crashes when running the last line of the method:
[pool release];
What am I doing wrong ? How can I fix this ?
Regards
Alan
First get a general understanding of the objective c memory management. You are confusing a lot of different things here. For example you don't have to retain the m_object since alloc already sets up the retain count with 1. Also normally you dont release you AutoReleasePool when you release a object. Like I said look up the documentation for memory management (pretty good actually).
Autorelease pools handle objects that have been specifically autoreleased
Example:
[object autorelease];
You have to have at least one NSAutoreleasePool in your program in case some code attempts to autorelease an object. If this is your only NSAutoreleasePool then releasing the pool maybe causing your problems.
I am calling a function repeatedly with a loop, and the loop runs inside of a thread. The thread has an autorelease pool.
I have the following code inside that function:
NSXMLDocument* undoXML;
NSData* undoData = [NSData dataWithContentsOfFile:undoFilePath];
undoXML = [[NSXMLDocument alloc] initWithData:undoData options:NSXMLDocumentTidyXML error:&err];
NSData* undoData2;
undoData2 = [undoXML XMLData];
[undoData2 release];
[undoXML release];
I'm getting the following strange results:
My program is leaking memory every time this function is called by the loop.
When I add the following code to the function:
NSData* undoData3;
undoData3 = [undoXML XMLData];
[undoData3 release];
My program leaks even more memory than before.
I'm really confused and I badly need help figuring out what's going on. Maybe my autorelease pool isn't working correctly? Why is this happening?
Are you sure it is leaking? Or is it simply growing in size?
What does your loop look like and how is the autorelease pool integrated into it?
The autorelease pool must be inside the loop or your loop will just build up tons of memory over time. That the leaks instrument doesn't show leaks indicates that you have violated the memory management rules or your loop is incorrect.
Try running Instruments on your project w/ the leak detection settings. This should identify exactly where your leak is occurring (even in the system libraries).
Run -> Run With Performance Tool -> Leaks
undoData should be preset to be autoreleased (according to naming convention dataWithContentsOfFile: returns an autoreleased object). But unless you have your own autorelease pool, nothing that is set to autorelease will actually be deallocated until the active pool is drained (i.e. sometime after your function returns).
Your thread may have its own autorelease pool, but unless you are creating one inside your own function, nothing will be deallocated until after your function exits.
If you want to trigger the draining of autoreleased objects in the middle of a function (say once per loop), you need to manage your own autorelease pool.
while(looping) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// do stuff that produces autoreleased objects
[pool drain];
}
Also, per cobbal's comment on your question, it looks like you should not be releasing undoData2 (or undoData3). Based on the naming convention -[NSXMLDocument XMLData] should be returning an autoreleased object.
If you have access to the source code of the NSData class you should look at what objects are being instantiated when undoData3 is created. I say this because you create the object and immediately destroy it. The issue must be that memory is being allocated inside the class but not being deallocated in it's destructor.