use of [release] in objective C - objective-c

I have a doubt regarding memory management in Objective-C.
-(void)viewDidLoad
{
NSNumber *num=[[NSNumber alloc] initWithInt:10];
[num release];
NSLog(#”%i”,num);
}
The above code is working fine by printing the value. But as soon as the object has been released it loses its value right? Then how come its working fine?

Here's what's going on. First you do this:
NSNumber *num=[[NSNumber alloc] initWithInt:10];
Your num variable now contains a pointer to an NSNumber object, and (because you used alloc) you own that object. Then you do this:
[num release];
When you sent release to the object, you relinquished your ownership of it. The object might still exist and be unchanged, or it might have been destroyed. You don't know. Your num variable still contains the same pointer, but the memory it points to might not be a valid object now so you cannot safely send messages to that object.
Then you do this:
NSLog(#”%i”,num);
In this NSLog statement, you are treating num as an integer, not as a pointer, because %i formats an integer. You're just printing the address (memory location) where the NSNumber object was (and might still be - you don't know). So it doesn't matter whether num points to a valid object or not; you're just treating num as an arbitrary int. You're not trying to send any messages to the NSNumber object.

By Calling [release] on object we can decrement retain count of the object.
If object is created by calling method which is having copy, new, alloc in it the caller is said to be owner of that object and owner
should alway release owned object.
If you are not owning the object you should not release it.
Always call release on object when object is retained which means if one call retain method the corresponding release call should be
invoked .Retain release should be matched.

Related

Memory management in local variable objective-c

In one interview i was asked to implement NSArray's exchangeObjectAtIndex:withObjectAtIndex: method.
I wrote the following code:
- (void)exchangeObjectAtIndex:(NSUInteger)index1 withObjectAtIndex:(NSUInteger)index2 {
id tmp = [self objectAtIndex:index1];
[self replaceObjectAtIndex:index1 withObject:[self objectAtIndex:index2]];
[self replaceObjectAtIndex:index2 withObject:tmp];
}
Interviewer said here's a memory management problem in first line and I'm going to catch bad_access_exc.
He recommended to write as this:
- (void)exchangeObjectAtIndex:(NSUInteger)index1 withObjectAtIndex:(NSUInteger)index2 {
id tmp = [[[self objectAtIndex:index1] retain] autorelease];
[self replaceObjectAtIndex:index1 withObject:[self objectAtIndex:index2]];
[self replaceObjectAtIndex:index2 withObject:tmp];
}
I understand that his code is right, but since tmp is local variable and it's going to be assigned, so there's no releasing and everything is gonna be ok. Is there any error?
If you are using manual memory management, there is an error. Apple has documented the problem under “Avoid Causing Deallocation of Objects You’re Using” in the Advanced Memory Management Programming Guide.
Specifically, objectAtIndex: doesn't retain and autorelease the object that it returns to you. So the NSArray might have the only “owning” reference to the object. Assigning to tmp under manual retain counting (MRC) doesn't retain the object so tmp doesn't own it and the autorelease pool doesn't own it.
This means that when line 2 of your method sends [self replaceObjectAtIndex:index1 withObject:[self objectAtIndex:index2]], the array might release the last reference to the object, deallocating it. At that point, tmp refers to a deallocated object; this is called a “dangling reference”.
Then in line 3, you try to put the dangling reference in the array. The array will send retain to the reference, which is invalid, and you will crash or experience heap corruption.
Under ARC, assigning to tmp does retain the object, so there is no error in that case.
Remember that id tmp is nothing more than a pointer to the object in your array. It doesn't say anything about the memory management of the object it's pointing to.
...it's going to be assigned, so there's no releasing...
This is the sticking point here. You can't guarantee that the object at index1 won't be deallocated when you replace it with the object at index2. In fact, the array will call release on it at this point to balance out the retain it called on the object when it was originally added to the array. Thus, it's possible that when the object at index1 is replaced will the object at index2, the reference count of the object at index1 will go to zero, the object will be deallocated, and your tmp variable will turn into a dangling pointer. The ... retain] autorelease] dance keeps the object around long enough to do the swap without having to worry about it deallocating before the end of the method (likely it will stick around until the top of the next run loop).

objective c memory manegment when returning objects from another object

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.

Question about NSMutableArray, pointers and release

How exactly does the addObject method of NSMutableArray work? Does it create a new instance and add it into the array or does it simply add a reference to the SAME object into the array?
If the answer is it only insert a reference to the object, then it leads to my next question:
Let's say I have the following method in one of my class ('list' is a NSMutableArray), gladly, this code works the way I wanted, but i just don't seem to fully understand why:
-(void)buyItem:(Item *)anItem
{
Item * newItem = [[Item alloc]init];
newItem.name = anItem.name;
newItem.details = anItem.details;
[list addObject:newItem];
[newItem release];
}
So basically after calling [list addObject:newItem], there would now be total of two reference pointing to the same object right(newItem, and another one in the 'list' array)?
But why does releasing the newItem object here, doesn't wipe out the one in the 'list' NSMutableArray? Aren't they pointing to the same Object?
When you are adding object to NSMutableArray using method addObject: it retains added object. This is why you can release it later and use afterwards by accessing using objectAtIndex: method.
It adds a reference and then increases the objects retain count by one. What you are doing is correct and it will still exist in the array with a retain count of one.
For your reference.
What increases an object's retain count?
It's important to understand the distinction between release and dealloc. release simply decrements the "retain count", except that when the count is decremented to zero, release goes on to dealloc the object.
In general (except where documented otherwise), when you pass an object reference (ie, pointer) to an Objective-C object, and it keeps a copy of that reference beyond the duration of your call to it, it retains the object on its own behalf, and it takes the responsibility to release the object when it is itself deallocated, or when the copy of the reference is nullified or overwritten.

what's the difference between two code scenario

Scenario1:
NSDictionary *dictionary =
[[NSDictionary alloc] initWithContentsOfFile:plistPath];
self.stateZips = dictionary;
[dictionary release];
Scenario2:
self.stateZips = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
dependes on stateZips property.
If it is retained:
Scenario 1: stateZips is properly retained ( a release on stateZips will call its dealloc). also local dictionary is released then and there.
Scenario 2: stateZips is retained twice ( a release in stateZips will not call its dealloc as it is still retained).
If it is assigned:
Scenario 1: stateZips points to released dictionary and accessing it else where might result in crash.
Scenario 2: stateZips is properly retained ( a release on stateZips will call its dealloc).
copy is not being considered, as i believe its not your intention (at least in this piece of code)
Both cause self.stateZips to be set to a dictionary initialized with the file pointed to in plistPath.
But in the second, the pointer to the initialized dictionary was not saved, and as it's an object with a retain count of +1 technically a release message needs to be sent to it in some place, to balance the memory management. But as there is no way to retrieve the pointer to that object, you'll end up with a memory leak.
Two exceptions apply:
1.Garbage Collection
If you're in a garbage collected environment, both are the same. Well, they are not the same, but the result is similar.
2.Property type
If the setter for stateZips simply assigns the pointer, then you can release the object using the ivar pointer. Then these two pieces of code have only one difference: in the former, the object is released right after it's used. In the latter, it's just "undefined". Without the context, it's hard to determine if this object was released or not, and when.
I am assuming that stateZips is a property with the retain attribute.
In Scenario 1. A dictionary is created with a retain count of 1 in the first line. In the second line the property will call retain again, increasing the retain count to 2. Finally the retain count is decremented by the release. This will leave the dictionary with the correct retain count.
In Scenario 2, the retain is only called once.
The net effect of the two scenarios is the same. The dictionary object will be retained, and you will need to include a release in the dealloc method of the class.
If this were not correctly handled by the compiler, it would be very hard indeed following the retain/release rules of objective-c.

Objective-c dealloc of boolean value

How would I dealloc a boolean value?
Deallocing it this way below gives me a warning: Incompatible pointer to integer conversion assigning to 'BOOL' (aka 'signed char') from 'void *'
- (void)dealloc {
self.booleanVar = nil;
[super dealloc];
}
Perhaps I should clarify, this is from a simple class inherited from NSObject.
I'm using the self.var = nil pattern that you see in Cocoa Touch classes. Let's say if it was an NSString* instead should I use self.var = nil or [var release] in the deallocmethod? I'm a little confused here.
You don't need to do it. It is not an object. This also explains the warning, as you're trying to assign a nil pointer (that's a NULL for objects basically) to a non-object.
Regarding your second question, yes. You can think of primitive variables as being part of the object, so when it's deallocated the vars will not exist anymore.
But when you have a NSString * in an object, it's just a pointer to another object. If you dealloc the former, the pointer will be deleted, not the NSString. No one might point to it, it's kind of lost in the air, occupying memory. So, before deleting the pointer, if you won't need the object anymore, you send it a release message. That's done in the dealloc method, since it's called to "delete" and object and thus is a good place to delete also every other object that has no use anymore.
You dont need to dealloc a BOOL, since BOOLs are really just a byte, which is a primitive data type. You only need to dealloc objects which have been allocated to memory.
First of all, if booleanVar is just a plain BOOL value, as in it is declared like so:
BOOL booleanVar;
then you do not need to free up any memory associated with it, since that memory is allocated and freed when the class that holds it is allocated and deallocated. So no code for booleanVar in dealloc will be fine.
However, if you are talking about a pointer for a BOOL, defined like so:
BOOL *booleanVar;
and what you want is to set this variable to a non-value, you should set it equal to NULL instead of nil, since NULL is for value pointers and nil is for object pointers (see: NULL vs nil in Objective-C).
However, if what you want is to free up the memory that the BOOL pointer points to, allocated with malloc or realloc, etc, then try the free() C function (see: http://www.cplusplus.com/reference/clibrary/cstdlib/free/).
What would really clear all this up is if you showed us the property declaration for booleanVar in the class interface, which would tell us exactly what you want to do and you would get an answer with complete certitude.