Objective-C #autoreleasepool? - objective-c

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

Related

Memory Management in a Objective-C static library

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.

ARC reference counting dealloc, and release

I am getting a bit confused. I am creating an app with storyboard, and running it on iPad 1. the application uses a lot of memory, so reached the 120mb, crashes. accordingly to what I have understood to remove this problem you need to release, dealloc... the point is that with ARC this should be automatic. In fact if I add for e.g.: [label1 release]; it gives me an error. But this ARC automatic release and dealloc does not seem to work! Is this because there are different ways to release with ARC??
You don't need to manually retain/release/autorelease with ARC. However if you have active references to a lot of unused objects they will still remain in memory. Profile your app with Instruments and it will show you how many objects you're creating of each class and how much memory they're consuming.
With ARC you still need to think about memory usage you just don't need to worry as much about memory leaks.
NSObject *bigMemObj = [[BigMemClass alloc] init];
//This creates the object in memory. In both arc and manual counting the retain count is 1
//Do stuff
//Prior to ARC you would have had to call [bigMemObj release]; before setting the variable to nil
bigMemObj = nil
//With ARC you don't have to do anything. The compiler inserts the release at compile time
Also read the documentation on declaring iVars __strong vs __weak.
Without looking at your code it's hard to identify what is consuming all the memory but hopefully that should help you determine where to start looking.
You should implement #autoreleasePool{} inside each method. In essence, each method will look like the following:
-(void)methodName{
#autoreleasePool{
//do method stuff
}
}
This will ensure that, upon exiting the autoreleasePool, memory is properly released.
I can't vote this back up, otherwise I would. I think Alessandro is asking about ARC vs using release and dealloc, not about what he's loading!
So, Alessandro, your understanding is correct that with ARC you don't release or dealloc. Therefore, those won't work if you're using ARC. Also, there is no alternative to release/dealloc, since ARC doesn't use it.
My suggestion would be to look at what you're using in the app that is taking up all this memory. Do you have a large number of pictures, for example, that are very large? Keep any graphics as small as possible, matching the resolution of the iPad. Especially the iPad 1, which doesn't have the "retina display".
You can use Autorelease pools in ARC. Here is some documentation on when to use them:
NSAutoreleasePool Class Reference
Advanced Memory Management Programming Guide: About Memory Management

scope of autorelease pool

Does NSAutoreleasePool also covers variables in all the called methods?
If that's the only place where -isNotExpired is called, the auto release pool you've set up will contain objects autoreleased in -isNotExpired (including startDate).
Note that in a normal Cocoa application, NSApplicationMain() called in main() in main.m will create an autorelease pool for you, so this code wouldn't leak anyway. You generally only create your own autorelease pool in cases where you'll be generating lots of temporary objects with a short useful life (in a loop for instance) and want to keep your high water memory usage down.

Memory leaks in Xcode 4.2 and iOS 5

I use xcode 4.2 and this use ARC (Automatic Reference Counting).
This is not memory leak, because ARC send message of 'release':
NSNumber *xy = [[NSNumber alloc] init];
But it's possible to create memory leaks with this:
char *oldString = "Old String";
char newStrig = strdup(oldString);
I wanted to know that other types of memory leaks can be made?
(If is possible without using C or C++)
ARC only applies to Cocoa memory management. If you are casting between Cocoa and CoreFoundation for the toll-free bridge objects there are macros to transfer the memory-management.
You can leak memory in C, you can leak Core Foundation memory, and the static analyser helps with finding those.
ARC doesn't do away with memory management completely. It removes the need to manage memory for Cocoa objects and in some cases (because it can optimise away some retain release calls) is more efficient in managing memory, but you still need to understand memory management for Core Foundation objects, and for C memory.
You also need to understand Cocoa memory management to understand when to use strong, weak, or copy properties, and when to use Block_copy() and Block_release() on blocks, even though blocks are Cocoa objects and in most cases the correct memory management is handled for you with ARC.
Again; ARC doesn't do away with memory management. It simplifies it, and reduces the amount of code you have to write, but you still have to understand what is being done for you behind the scenes, and when you need to manage your own memory.
ARC can only work if you are using Objective-C memory allocations because its tied exclusively to that. In fact when you are using ARC the compiler does its best to match every alloc with an release (it cannot even guarantee that).
If you are using any other means than Objective-C allocations you are on your own again. ARC won't handle that.

Under ARC, is it still advisable to create an #autoreleasepool for loops?

Let's say that I have a loop that returns a bunch of autoreleased NSData objects...
NSData* bigData = ...
while(some condition) {
NSData* smallData = [bigData subdataWithRange:...];
//process smallData
}
Under ARC, should I still wrap an #autoreleasepool around the while condition?
NSData* bigData = ...
#autoreleasepool {
while(some condition) {
NSData* smallData = [bigData subdataWithRange:...];
//process smallData
}
}
The reason why I'm asking is I see the living allocation count in instruments going through the roof for my NSData objects that invoke a dataWith... method as opposed to an initWith... method. When I use initWith..., the living allocation count is much, much less.
Is it better to prefer the initWith... methods whenever possible?
Yes you should still use autorelease pools when using convenience methods in a tight loop. All the old memory management rules still apply under ARC, the compiler is merely injecting RRs for you. Checkout the great post by the awesome Mike Ash!
Link
I think your issue is that the autorelease pool is supposed to go inside the loop. With the loop inside the autorelease block rather than vice-versa, the accumulated objects won't be released until after the loop finishes.
Under ARC, should I still wrap an #autoreleasepool around the while condition?
Yes. Autorelease Pools are still in place, and grow and pop as before. The compiler just adds and coalesces the necessary retains and releases operations when ARC is enabled (echoing Logan), based on the methods that are visible to the TU and default naming conventions.
Execution in ARC is nearly identical the manual reference counting: Autorelease pool stacks still exist. One difference is that the compiler may order the reference counting operations slightly different from the way you wrote it (not in an incorrect way), and may omit unnecessary retain cycles.
Is it better to prefer the initWith... methods whenever possible?
WRT minimizing heap growth compared to the autoreleased counterparts: Yes. That's always been the case. It's especially important on iOS devices, where memory is quite limited.
The exception to this is when the object may avoid an allocation. Example:
NSString * copy = [NSString stringWithString:arg];
in this case, copy may be [[arg retain] autorelease]. Note that in this case, copy is still autoreleased, but you should not usually go to great lengths to test the presence of such optimizations. Note: It's also better to use copy = [arg copy]...[arg release] here.
The other bonus is that your ref count imbalances are often caught earlier when the object is never autoreleased, and closer to the call site (rather than when the Autorelease Pool is finally popped).
Performance with large autorelease pools is actually much worse than most people would suppose. If you can avoid depending on them heavily (e.g. using alloc+init...+release), you can make your program noticeably faster. Explicitly creating autorelease pools is cheap, and can help minimize this problem. When allocations are large and/or numerous, avoid using autorelease on them where possible, and do wrap these sections in explicit autorelease pools.