objective c memory manegment when returning objects from another object - objective-c

I am having problem with understanding one concept of memory managment, because I am new to objective C. For instance lets say I have a class Bar and Foo.
in main function I call:
Foo *foo = [bar getFoo]; //In my bar method I return foo
[foo retain];
[foo callMethod];
[foo release];
I know this is right way to do it. But why do we have to retain it after we get it from another object, does not this mean returning object has retain count 0 ? so we have to reatin it to count 1 to use it? but if it has reatin count 0, how do we know it is still there. We can assume since it is the next line that increment retain count that the object memory wont be realocated, but what if we have multi-threading program?

When an class method returns an object, it will autorelease it so you don't have to bother; typically:
- (Foo *)getFoo
{
return [[_foo retain] autorelease];
}
If you are only using foo for the lifetime of the calling method you don't need to retain it, as it won't be autoreleased until next time through the run loop, so your code should actually be:
Foo *foo = [bar getFoo]; //In my bar method I return foo
[foo callMethod];
If, however, you want to hold foo for a while, outside the scope of the calling method, you need to retain it and then release it sometime later.
One more thing; the convention for getter method names is simply "name", so your setter should be setFoo and your getter would be foo. Keeping to the naming conventions is a good idea as it lets you know what a method does, in say 7 months time, and tools like static analysis understand the conventions.

The method getFoo doesn't return an object with a 0 retain count. It returns an object with a +0 retain count which means that:
the object's retain count is not null (otherwise, the object wouldn't exist)
and the retain count wasn't altered by the invocation of the method, or if it was, it was in a balanced way (with as many release/autorelease as retain/alloc/new/copy).
Thus the lifetime of the object entirely depends on where and how it is retained. We don't know how long the object will be valid as any method invocation could release the object.
For example, let's consider the following code:
id anObject = [anArray objectAtIndex:0];
[anArray removeObjectAtIndex:0];
The object anObject isn't retained any more by the array as we removed it. Therefore it may have been destructed (but maybe it wasn't because it is still used somewhere else).
Generally, when getting an object from a method (other that alloc, copy, new or retain), we can assume that:
either the object was retained then autoreleased,
either the object is retained by the object that returned it.
So we know the object foo is valid until we return from the current method/function or we invoke a method/function that alter the state of the object bar, whichever comes first. After that, it may have been destructed.
So in your case, you can safely omit the retain/release pair.
However, it is very difficult to guaranty that an object doesn't get released unless we know the implementation of every method we invoke. Therefore, retaining (then releasing) every single object we get is the safer approach and that's what the compiler will do when you enable ARC (Automatic Reference Counting).
But that would require you to write a lot of retain/release and your code would become difficult to read, understand and maintain. Moreover, the more code you write, the more bugs you get (unless you never write bugs).
In conclusion, you don't need to retain an object unless you have a reason to suspect it could vanish otherwise.

Related

Why alloc method can add retain count

When we call alloc with a Class, I know that count of Object will +1. For example: NSObject *obj = [NSObject alloc];, The reference count of obj will be 1. I read the source code, but I can't find some code that can tell me why alloc can add the reference count. And some blog said alloc will call retain method, so it can +1. But I can't find some code can prove this. Can some one tell me why alloc will add reference count?
You cannot find generic code that adds one in +alloc. Usually inside +alloc the object is newly created and gets the RC 1. (So you can say that 1 is added, because the object before its creation has an RC of 0. Of course, this is not formally correct, because before the creation there is no object, therefore it cannot have an RC. Akin of the zero is null antipattern.)
However, classes can overwrite +alloc to return an existing object instead of a new one. For example this has been done in the past for implementing singletons. In such a case +alloc had to signal the new reference (+alloc does an ownership transfer) and really had to add 1. Something like this (sample code):
+(id)alloc
{
if(mySingleton==nil) // it is not already created
{
return mySingleton = [super alloc];
}
return [mySingleton retain]; // ownership transfer
}
I think the idea of saying "+1" instead of "1" in some articles is, that you should view every reference separately. So there is no absolute value of RC. Whatever you do with a reference and its object is relative to the situation before you did it. For this reason some authors always describe the RC with "+1" and "-1". Of course, this is meaningless, if an object is newly created.
alloc does not increase the count. There is not any object until you call alloc, so there is nothing to count. The object comes into existence with one reference, and so it comes back from alloc with a retain count of positive 1.
(Conversely, if there is ever less than one reference, the object is dead.)

Does copy also transfer the retain count?

Suppose I have an object, for example an NSString, with retain count 5. When I call copy on it, I get a new copy of the object; does this new object have the retain count of its original object ?
It depends. copy is a convenience method for copyWithZone:,
and the "NSCopying Protocol Reference" states:
Your options for implementing this protocol are as follows:
Implement NSCopying using alloc and init... in classes that don’t
inherit copyWithZone:.
Implement NSCopying by invoking the
superclass’s copyWithZone: when NSCopying behavior is inherited. If
the superclass implementation might use the NSCopyObject function,
make explicit assignments to pointer instance variables for retained
objects.
Implement NSCopying by retaining the original instead of
creating a new copy when the class and its contents are immutable.
(I have modified the following two statements after all that feedback.)
For example, NSString is an immutable object, and copy just retains the object
and returns a pointer to the same object. Retaining the object might increase the
retain count, but not necessarily (as in the case of string literals.)
Copying an NSMutableString would probably create a new object and return that.
The new object would have its own retain count independent of the original object.
But you should not care about the difference. With manual reference counting,
copy returns an object that you own and have to release eventually.
With ARC, the compiler with automatically handle that.
copy returns an object that is a semantic [shallow] copy(1) of the object. What the copy method returns is an implementation detail; it may return the same object, it may return a different instance of the same class, or it might even return an instance of a different class.
Doesn't matter.
What matters is that the returned object, under manual retain/release, has a retain count of +1. Not 1, but +1. It might actually be 1, 42, 981, or -1. Doesn't matter.
All that matters is that you must balance that retain with a release or autorelease somewhere if you want to relinquish the object back to the system. Which may not actually cause it to be deallocated; that is an implementation detail of no concern (until optimization time, anyway).
(1) semantic [shallow] copy means that the object returned is an effective shallow copy. The state contained within the copied object (but not within objects contained within the object -- that is the shallow part) will not change when the original object changes state. For a mutable object, copy must actually create a new instance of some object -- most likely an immutable variant class -- that can contain the original state.
For an immutable object, the copy method might be simply implemented as return [self retain];. Or, in the case of static NSStrings (NSCFStrings), it might simply be return self; as retain/release/autorelease are no-ops on such strings.
No, a copied object will have a retain count of 1, just like a newly initialized object.
I highly recommend you read the Memory Management Guide if you wish to learn more.
If you're new to iOS development, the iOS App Programming Guide should be read first, and is a great use of your time.
I just noticed you didn't tag this as iOS specific, if you're coding for Mac, the Programming with Objective-C guide might be more appropriate for you.
To really get your head around this issue, don't think in terms of retain count, think in terms of pointer ownership (like ARC does).
If an object has a "retain count" of 5, that means five pieces of code somewhere are each holding a (strong) pointer to its memory address. If you copy that object, you get a pointer to the address of the new, copied object. The other five pieces of code are still pointing to the original object. There's only one piece of code pointing to the new object, so its "retain count" is one.
As noted in other answers, the Memory Management Guide definitely helps make this all clear.
Why did I put "retain count" in quotes? Because it's only useful as a general concept -- you shouldn't be using retainCount directly, or you'll hear from #bbum.
Objective-C plays some clever tricks when you ask it to copy objects, and as a result retain counts might not be what you think they should be.
Let's say you have an object pointer x with a retain count of n, and call the copy method which returns an object pointer y.
NSObject* x = ...;
NSObject* y = [x copy];
Then the rule is that if you release x n times, and release y once, all objects will be gone. Usually this is achieved by leaving x unchanged, and giving y a retain count of 1.
However, if x points to an immutable object, then Objective-C may decide that no copy needs to be done. The result is that y = x. Still, the rule above still applies: Releasing x n times and y once (even though they are the same object) will free all the objects involved. That's achieved by the copy method returning x with a +1 retain count.
Copy on mutable object like NSMutableArray will create a new copy and retain count will be 1 while copy immutable object like NSArray will point to same reference and increase the retain count by 1.

When and when to not allocate memory to objects

NSArray *array = [dictionary objectForKey:#"field"];
and
NSArray *array = [[NSArray alloc] initWithArray:[dictionary objectForKey:#"field"]];
I see both kind of approaches very frequently in objective C code.
When tried to understand, I found both of them used in similar situation too, which makes contradiction. I am not clear on when I should use 1st approach and when 2nd one?
Any idea?
Detailed explanation and useful references are moms welcome.
First off, those two examples are doing slightly different things. One is retrieving something from an existing dictionary and one is creating a new array by retrieving something from an existing dictionary (the value of that key is an array).
But, if you're asking the difference between getting objects by alloc vs. convenience methods. ([NSString alloc] init vs [NSString stringWith ...), by convention, you own anything that you call alloc, new copy or mutableCopy on. Anything that you call that is not those, is autoreleased.
See the memory guide here. Specifically, look at the rules.
Getting an autoreleased object means it will go away at some point in the near future. If you don't need to hold onto outside the scope of that function, then you can call autorelease on it or use one of the convenience methods that's not alloc, etc...
For example:
// my object doesn't need that formatted string - create the autoreleased version of it.
- (NSString) description {
return [NSString stringWithFormat:#"%# : %d", _title, _id];
}
// my object stuffed it away in an iVar - I need the retained version of it. release in dealloc
- (void) prepare {
_myVal = [[NSString alloc] initWithFormat:"string I need for %d", _id];
}
In the first example, I created a convenience methods for others to call, my class doesn't need that object beyond the scope of that method so I create the autoreleased version of it and return it. If the caller needs it beyond the scope of his calling method, he can retain it. If not he can use it and let it go away. Very little code.
In the second example, I'm formatting a string and assigning it to an iVar variable that I need to hold onto for the lifetime of my class so I call alloc which will retain it. I own it and releasing it eventually. Now, I could have used the first version here and just called retain on it as well.
You have a fundamental misunderstanding of allocations versus instance methods.
The first example, NSDictionary's -objectForKey method, returns id, not an instance of NSDictionary, therefore it does not allocate or initialize the variable.
The second, however is the classic retain part of the retain-release cycle.
The two methods are fundamentally equal (if we are to assume that array is alloc'd but empty in the first, and nil in the second), and both get ownership of the array object. I would go with the second, as it guarantees a reference, and it's shorter.
What I think you're confusing this with are new and convenience methods. Convenience methods (like NSNumber's +numberWithInt:, NSString's +stringWithFormat:, and NSMutableArray's +array), return an autorelease instance of the class (usually). New takes the place of alloc and init in just one word.

Are these two Objective-C message expressions equivalent memory-wise?

Do the following two message expressions result in an increase of retain count in the same object?
Example 1:
iVar = [Foo aClassMethodInFoo];
[iVar retain];
Example 2:
iVar = [[Foo aClassMethodInFoo] retain];
Example 1 is explicit in that it's iVar instance whose retain count is increased.
Example 2 seems to suggest that it's retain count of the object returned from [Foo aClassMethodInFoo] that is increased. If that is so, then assuming aClassMethodInFoo is a convenience method, which object do I 'release' to balance the earlier 'retain' in order not to leak memory?
Both are absolutely identical. In the first case, you're assigning the results of a method call to a variable, then calling -retain on that variable. The net result is the variable holds the object, and you've called -retain on the object. In the second case, you're calling -retain on the results of a method call, and assigning the result of that to the variable. As -retain is guaranteed to return its receiver, the net result is the variable holds the object, and you've called -retain on the object.
In both cases, the memory semantics are precisely identical. According to the naming conventions defined in the Memory Management Programming Guide, a method named +aClassMethodInFoo returns an autoreleased object, so your call to -retain is correct if you're storing the results in an ivar. As such, when you're done you can call -release on your ivar. Your question of "which object do I 'release'" is nonsensical because there's only one object here.
Assuming that the class method returns a new object rather than void, they are exactly equivalent because retain just returns self.

Another "Retain, then Release" question

being a Cocoa/Obj-C newbie I am going through the "Cocoa Programming for Mac OS X" book by Aaron Hillegass and - leaving apart the fact that now we have also the chance to use GC to avoid all this reasoning - I am not sure I get the reason for some of those retains.
In particular in one of the examples Aaron gives as good programming practice:
- (void) setFoo:(NSCalendarDate *)x
{
[x retain];
[foo release];
foo = x;
}
I don't get the reason for retaining the x instance at the first line of the method:
[x retain];
The scope of this instance is just the set method, right?
When exiting the method scope the x instance should be deallocated anyway no?
Besides, when assigning x to foo with:
foo = x;
foo will be anyway pointing to x memory cells and will therefore increment the pointed object retain count, no? This should ensure the memory won't be deallocated.
So, what's the point? I am sure I am missing something, of course, but don't know what exactly.
Thanks,
Fabrizio
Retain means: I will be needing this object to stay around, it must not be deallocated. If x wouldn't be retained, the following is likely to happen:
You assign x to foo, so foo now points to the address where your NSCalendarDate is. Someone releases or autoreleases this object, it's retain count eventually drops to 0 and the object is deallocated. Now your foo still points to that address, but there's no longer a valid object. Sometime later, a new object is created and by chance it's situated at the same address than your old NSCalendarDate object. Now your foo points to an entirely different object !
To prevent that, you need to retain it. You need to say, please do not deallocate the object yet, I need it. Once you're done with it, you release it which means I no longer need the object, you can clean it up now if nobody else needs it.
Now for the classical three part assignment. Consider your setFoo: would look like this:
- (void) setFoo:(NSCalendarDate *)x
{
[foo release];
[x retain];
foo = x;
}
This is a very bad idea. Consider your object is the only one who has retained the NSCalendarDate object, and consider you would then do: [self setFoo:foo];. Might sound silly, but something like this can happen. The flow would now be this:
foo would be released. Its retain count might now drop to 0 and the object will get deallocated.
Whoops, we're trying to retain and access a deallocated object.
This is why you always first retain the new object, then release the old object.
If you're coming from a Java or .NET background, it is very important to understand that a variable of type Foo * only contains the address of your object, nothing more. In Java or .NET, a variable that points to an object automatically "retains" it, if you will. Not so in Objective-C (in non-GC environments). You could consider a variable of type Foo * to be a weak reference, and you explicitly need to tell Objective-C whether you will still need that object at that address or not.