Memory Management in a Objective-C static library - objective-c

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.

Related

Usage of autorelease pool in objectAtindex swizzling for NSMutableArray

- (nullable id)myObjectAtIndex:(NSUInteger)index{
#autoreleasepool {
id value = nil;
if (index < self.count)
{
value = [self myObjectAtIndex:index];
}
return value;
}
}
I have no idea about the purpose of using autoreleasepool here. Can someone give me a hand?
Unless I'm missing the obvious, which is always possible, we can only guess:
There is a stack of autorelease pools, the top of the stack being the one in use. When the #autoreleasepool { ... } construct is entered a new pool is created and pushed on the stack, on exit from the construct the pool is drained and popped off the stack.
The reason to create local pools is given in the NSAutoReleasePool docs (emphasis added):
The Application Kit creates an autorelease pool on the main thread at the beginning of every cycle of the event loop, and drains it at the end, thereby releasing any autoreleased objects generated while processing an event. If you use the Application Kit, you therefore typically don’t have to create your own pools. If your application creates a lot of temporary autoreleased objects within the event loop, however, it may be beneficial to create “local” autorelease pools to help to minimize the peak memory footprint.
So what is the purpose in the code you are looking at? Some guesses:
Either the original author knows/believes that the called methods count and objectAtIndex (post the swizzle) add a significant amount of objects to the autorelease pool and wishes to clean these up; or
The original author was/is planning to add future code to myObjectAtIndex which will add a significant amount of objects to the autorelease pool and wishes to clean these up; or
Wishes to be able to call objectAtIndex and ensure there is no impact on the memory used for live objects (e.g. maybe they were measuring memory use by something else); or
Who knows, accept the original author (hopefully!)
HTH
There is no scientific reason.
The whole code is an example of "this app crashes and I do not know why" panic code:
Obviously the author had a problem with guaranteeing correct indexes, what would be the correct approach. Therefore he wrote a special method to "repair" it. The naming ("my") shows, that he thought: I can do it better (instead of insuring correct indexes).
Moreover, adding an ARP to a piece of code, that obviously does not create an bigger amount of objects, is a sure sign for the fact, that he couldn't oversee his code anymore.
Move the whole code to /dev/null.

Do I need to use autorelease on object which created not using alloc init? [duplicate]

I'm just beginning to have a look at Objective-C and Cocoa with a view to playing with the iPhone SDK. I'm reasonably comfortable with C's malloc and free concept, but Cocoa's references counting scheme has me rather confused. I'm told it's very elegant once you understand it, but I'm just not over the hump yet.
How do release, retain and autorelease work and what are the conventions about their use?
(Or failing that, what did you read which helped you get it?)
Let's start with retain and release; autorelease is really just a special case once you understand the basic concepts.
In Cocoa, each object keeps track of how many times it is being referenced (specifically, the NSObject base class implements this). By calling retain on an object, you are telling it that you want to up its reference count by one. By calling release, you tell the object you are letting go of it, and its reference count is decremented. If, after calling release, the reference count is now zero, then that object's memory is freed by the system.
The basic way this differs from malloc and free is that any given object doesn't need to worry about other parts of the system crashing because you've freed memory they were using. Assuming everyone is playing along and retaining/releasing according to the rules, when one piece of code retains and then releases the object, any other piece of code also referencing the object will be unaffected.
What can sometimes be confusing is knowing the circumstances under which you should call retain and release. My general rule of thumb is that if I want to hang on to an object for some length of time (if it's a member variable in a class, for instance), then I need to make sure the object's reference count knows about me. As described above, an object's reference count is incremented by calling retain. By convention, it is also incremented (set to 1, really) when the object is created with an "init" method. In either of these cases, it is my responsibility to call release on the object when I'm done with it. If I don't, there will be a memory leak.
Example of object creation:
NSString* s = [[NSString alloc] init]; // Ref count is 1
[s retain]; // Ref count is 2 - silly
// to do this after init
[s release]; // Ref count is back to 1
[s release]; // Ref count is 0, object is freed
Now for autorelease. Autorelease is used as a convenient (and sometimes necessary) way to tell the system to free this object up after a little while. From a plumbing perspective, when autorelease is called, the current thread's NSAutoreleasePool is alerted of the call. The NSAutoreleasePool now knows that once it gets an opportunity (after the current iteration of the event loop), it can call release on the object. From our perspective as programmers, it takes care of calling release for us, so we don't have to (and in fact, we shouldn't).
What's important to note is that (again, by convention) all object creation class methods return an autoreleased object. For example, in the following example, the variable "s" has a reference count of 1, but after the event loop completes, it will be destroyed.
NSString* s = [NSString stringWithString:#"Hello World"];
If you want to hang onto that string, you'd need to call retain explicitly, and then explicitly release it when you're done.
Consider the following (very contrived) bit of code, and you'll see a situation where autorelease is required:
- (NSString*)createHelloWorldString
{
NSString* s = [[NSString alloc] initWithString:#"Hello World"];
// Now what? We want to return s, but we've upped its reference count.
// The caller shouldn't be responsible for releasing it, since we're the
// ones that created it. If we call release, however, the reference
// count will hit zero and bad memory will be returned to the caller.
// The answer is to call autorelease before returning the string. By
// explicitly calling autorelease, we pass the responsibility for
// releasing the string on to the thread's NSAutoreleasePool, which will
// happen at some later time. The consequence is that the returned string
// will still be valid for the caller of this function.
return [s autorelease];
}
I realize all of this is a bit confusing - at some point, though, it will click. Here are a few references to get you going:
Apple's introduction to memory management.
Cocoa Programming for Mac OS X (4th Edition), by Aaron Hillegas - a very well written book with lots of great examples. It reads like a tutorial.
If you're truly diving in, you could head to Big Nerd Ranch. This is a training facility run by Aaron Hillegas - the author of the book mentioned above. I attended the Intro to Cocoa course there several years ago, and it was a great way to learn.
If you understand the process of retain/release then there are two golden rules that are "duh" obvious to established Cocoa programmers, but unfortunately are rarely spelled out this clearly for newcomers.
If a function which returns an object has alloc, create or copy in its name then the object is yours. You must call [object release] when you are finished with it. Or CFRelease(object), if it's a Core-Foundation object.
If it does NOT have one of these words in its name then the object belongs to someone else. You must call [object retain] if you wish to keep the object after the end of your function.
You would be well served to also follow this convention in functions you create yourself.
(Nitpickers: Yes, there are unfortunately a few API calls that are exceptions to these rules but they are rare).
If you're writing code for the desktop and you can target Mac OS X 10.5, you should at least look into using Objective-C garbage collection. It really will simplify most of your development — that's why Apple put all the effort into creating it in the first place, and making it perform well.
As for the memory management rules when not using GC:
If you create a new object using +alloc/+allocWithZone:, +new, -copy or -mutableCopy or if you -retain an object, you are taking ownership of it and must ensure it is sent -release.
If you receive an object in any other way, you are not the owner of it and should not ensure it is sent -release.
If you want to make sure an object is sent -release you can either send that yourself, or you can send the object -autorelease and the current autorelease pool will send it -release (once per received -autorelease) when the pool is drained.
Typically -autorelease is used as a way of ensuring that objects live for the length of the current event, but are cleaned up afterwards, as there is an autorelease pool that surrounds Cocoa's event processing. In Cocoa, it is far more common to return objects to a caller that are autoreleased than it is to return objets that the caller itself needs to release.
Objective-C uses Reference Counting, which means each Object has a reference count. When an object is created, it has a reference count of "1". Simply speaking, when an object is referred to (ie, stored somewhere), it gets "retained" which means its reference count is increased by one. When an object is no longer needed, it is "released" which means its reference count is decreased by one.
When an object's reference count is 0, the object is freed. This is basic reference counting.
For some languages, references are automatically increased and decreased, but objective-c is not one of those languages. Thus the programmer is responsible for retaining and releasing.
A typical way to write a method is:
id myVar = [someObject someMessage];
.... do something ....;
[myVar release];
return someValue;
The problem of needing to remember to release any acquired resources inside of code is both tedious and error-prone. Objective-C introduces another concept aimed at making this much easier: Autorelease Pools. Autorelease pools are special objects that are installed on each thread. They are a fairly simple class, if you look up NSAutoreleasePool.
When an object gets an "autorelease" message sent to it, the object will look for any autorelease pools sitting on the stack for this current thread. It will add the object to the list as an object to send a "release" message to at some point in the future, which is generally when the pool itself is released.
Taking the code above, you can rewrite it to be shorter and easier to read by saying:
id myVar = [[someObject someMessage] autorelease];
... do something ...;
return someValue;
Because the object is autoreleased, we no longer need to explicitly call "release" on it. This is because we know some autorelease pool will do it for us later.
Hopefully this helps. The Wikipedia article is pretty good about reference counting. More information about autorelease pools can be found here. Also note that if you are building for Mac OS X 10.5 and later, you can tell Xcode to build with garbage collection enabled, allowing you to completely ignore retain/release/autorelease.
Joshua (#6591) - The Garbage collection stuff in Mac OS X 10.5 seems pretty cool, but isn't available for the iPhone (or if you want your app to run on pre-10.5 versions of Mac OS X).
Also, if you're writing a library or something that might be reused, using the GC mode locks anyone using the code into also using the GC mode, so as I understand it, anyone trying to write widely reusable code tends to go for managing memory manually.
As ever, when people start trying to re-word the reference material they almost invariably get something wrong or provide an incomplete description.
Apple provides a complete description of Cocoa's memory management system in Memory Management Programming Guide for Cocoa, at the end of which there is a brief but accurate summary of the Memory Management Rules.
I'll not add to the specific of retain/release other than you might want to think about dropping $50 and getting the Hillegass book, but I would strongly suggest getting into using the Instruments tools very early in the development of your application (even your first one!). To do so, Run->Start with performance tools. I'd start with Leaks which is just one of many of the instruments available but will help to show you when you've forgot to release. It's quit daunting how much information you'll be presented with. But check out this tutorial to get up and going fast:
COCOA TUTORIAL: FIXING MEMORY LEAKS WITH INSTRUMENTS
Actually trying to force leaks might be a better way of, in turn, learning how to prevent them! Good luck ;)
Matt Dillard wrote:
return [[s autorelease] release];
Autorelease does not retain the object. Autorelease simply puts it in queue to be released later. You do not want to have a release statement there.
My usual collection of Cocoa memory management articles:
cocoa memory management
There's a free screencast available from the iDeveloperTV Network
Memory Management in Objective-C
NilObject's answer is a good start. Here's some supplemental info pertaining to manual memory management (required on the iPhone).
If you personally alloc/init an object, it comes with a reference count of 1. You are responsible for cleaning up after it when it's no longer needed, either by calling [foo release] or [foo autorelease]. release cleans it up right away, whereas autorelease adds the object to the autorelease pool, which will automatically release it at a later time.
autorelease is primarily for when you have a method that needs to return the object in question (so you can't manually release it, else you'll be returning a nil object) but you don't want to hold on to it, either.
If you acquire an object where you did not call alloc/init to get it -- for example:
foo = [NSString stringWithString:#"hello"];
but you want to hang on to this object, you need to call [foo retain]. Otherwise, it's possible it will get autoreleased and you'll be holding on to a nil reference (as it would in the above stringWithString example). When you no longer need it, call [foo release].
The answers above give clear restatements of what the documentation says; the problem most new people run into is the undocumented cases. For example:
Autorelease: docs say it will trigger a release "at some point in the future." WHEN?! Basically, you can count on the object being around until you exit your code back into the system event loop. The system MAY release the object any time after the current event cycle. (I think Matt said that, earlier.)
Static strings: NSString *foo = #"bar"; -- do you have to retain or release that? No. How about
-(void)getBar {
return #"bar";
}
...
NSString *foo = [self getBar]; // still no need to retain or release
The Creation Rule: If you created it, you own it, and are expected to release it.
In general, the way new Cocoa programmers get messed up is by not understanding which routines return an object with a retainCount > 0.
Here is a snippet from Very Simple Rules For Memory Management In Cocoa:
Retention Count rules
Within a given block, the use of -copy, -alloc and -retain should equal the use of -release and -autorelease.
Objects created using convenience constructors (e.g. NSString's stringWithString) are considered autoreleased.
Implement a -dealloc method to release the instancevariables you own
The 1st bullet says: if you called alloc (or new fooCopy), you need to call release on that object.
The 2nd bullet says: if you use a convenience constructor and you need the object to hang around (as with an image to be drawn later), you need to retain (and then later release) it.
The 3rd should be self-explanatory.
Lots of good information on cocoadev too:
MemoryManagement
RulesOfThumb
As several people mentioned already, Apple's Intro to Memory Management is by far the best place to start.
One useful link I haven't seen mentioned yet is Practical Memory Management. You'll find it in the middle of Apple's docs if you read through them, but it's worth direct linking. It's a brilliant executive summary of the memory management rules with examples and common mistakes (basically what other answers here are trying to explain, but not as well).

Objective-C #autoreleasepool?

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

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.

Autoreleasing in Objective-C application when returning a value

I read the memory management guide for the Objective-C language, but this is a doubt I still have, even after reading many times the chapter.
Let's say I want to return an object I just created in a method of an object like this:
NSString* ret = [[NSString alloc] initWithString:#"My string"];
return ret;
I can do this, but it is not correct according to the ownership policy. The guide states that the correct solution would be to:
NSString* ret = [[NSString alloc] initWithString:#"My string"];
return [ret autorelease];
because, as I'm autoreleasing, I'm no more the owner.
My question is: when will the NSString be actually released and deallocated? When the last initialized pool is released? This means that, if I don't create a pool, this object will be released when the application is closed (the pool that xcode creates by default is released at the end). Is this correct?
The same applies to objects which are not allocated by me like:
NSString* ret = [NSString stringWithString:#"My string"];
? If I don't create a pool to release it elsewhere, it is released at the end of the application when the pool created by xcode is released?
Thanks for any clarification.
When you call autorelease, you're handing your ownership to the nearest autorelease pool, to be released at the next drain.
There must always be an outermost autorelease pool, but usually there will be other ones closer to the action. You don't have to create these explicitly -- though you can do that too -- they are created by the Cocoa framework in the course of going about the program's business.
If you're coding a non-GUI tool that never hands off to the framework, and you never create another pool, and never call drain on the existing one, then the object will be released when the pool itself is, just before exiting. Otherwise, it will most commonly be released at the end of the event handling cycle, which is one of the key places the framework maintains a pool.
In general, the case of objects created via convenience class methods is the same as those alloced and autoreleased. As it happens, the one you cite from NSString would be a little different because at its base is a constant string, and that doesn't get managed quite the same way. But that's an implementation detail.
Objects go into the current autorelease pool when they're autoreleased. When the pool itself is sent release (or drain, which is the same thing), the objects in it are also sent release. As for when the current autorelease pool will be created and released in most cases, the memory management guide chapter on autorelease says:
The Application Kit automatically creates a pool at the beginning of an event cycle (or event-loop iteration), such as a mouse down event, and releases it at the end
So in practice, autoreleased objects will go away very quickly — before the end of the app's lifetime, and in fact before the next touch/mouseMoved event message is sent.
It's possible to create your own local autorelease pool to make them go away even more immediately if you need to, but that's normally a micro-optimization that might actually make things go a bit slower (it increases the number of messages being sent without necessarily making anything else take less time).
Keep in mind that -autorelease is nothing but a delayed messaging facility. When you send -autorelease to an object, the current autorelease pool will add that object to its list, and when the pool is drained or released, it will send a -release message to every object in its list.