This is my sample code....i am creating the class object as NSDictionary.Here it shows the leak,Where i release that object it's not right place to release this object?
How can i release this object.
TanX in advance.
NSDictionary *locationDictionary = [[CJSONDeserializer alloc]deserializeAsDictionary:webresponse error:nil];
NSArray *placemarkArray = [locationDictionary valueForKey:#"Placemark"];
NSDictionary *tempDictionary = [placemarkArray objectAtIndex:0];
NSDictionary *pointDictionary = [tempDictionary valueForKey:#"Point"];
NSArray *coordinateArray = [pointDictionary valueForKey:#"coordinates"];
NSNumber *numberLongitude = [coordinateArray objectAtIndex:0];
NSNumber *numberLatitude = [coordinateArray objectAtIndex:1];
The CJSONDeserializer class has convenient constructor. So use that.
CJSONDeserializer *jsonDeserializer = [CJSONDeserializer deserializer];
The deserialize with that object.
NSDictionary *locationDictionary = [jsonDeserializer deserializeAsDictionary:webresponse error:nil];
So you need not to release that.
You are calling alloc on the CJSONDeserializer so you own it. When you are done with it, you need to release it. I don't see you calling release on it.
The rest of the variable are obtained by not calling alloc, copy, new or mutableCopy so you don't own them. They have been auto released. That's the convention.
This is a must read:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html
Specifically, the rules:
You own any object you create
You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or mutableCopy).
You can take ownership of an object using retain
A received object is normally guaranteed to remain valid within the method it was received in, and that method may also safely return the object to its invoker. You use retain in two situations: (1) In the implementation of an accessor method or an init method, to take ownership of an object you want to store as a property value; and (2) To prevent an object from being invalidated as a side-effect of some other operation (as explained in “Avoid Causing Deallocation of Objects You’re Using”).
When you no longer need it, you must relinquish ownership of an object you own
You relinquish ownership of an object by sending it a release message or an autorelease message. In Cocoa terminology, relinquishing ownership of an object is therefore typically referred to as “releasing” an object.
You must not relinquish ownership of an object you do not own
This is just corollary of the previous policy rules, stated explicitly.
If you are just after numberLong. and numberLat. retain just them until your done with them.
And if you no longer need the locationDictionary as a whole you can now [locationDitionary release], but only after retaining or finishing with what you need from it.
Related
What is the right way to get an NSString object from an NSArray, keeping Memory Managment in mind.
Suppose I have an array
NSArray *myNewArray = [[NSArray alloc] initWithObjects:.......];
Now I want to get an object from this NSArray at index 2.
NSString *nameString = [myNewArray objectAtIndex:2]; // is it the right way? how to deal with "nameString"
// now regarding memory managment, should I release it ?
OR I should first alloc nameString and then assign value to it ?
Check out the Cocoa Memory Management rules (how many times have I started a post with that sentence?). In particular
You only release or autorelease objects you own.
You take ownership of an object if you create it using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message.
You use release or autorelease to relinquish ownership of an object. autorelease just means “send a release message in the future” (specifically: when the used autorelease pool receives a drain message—to understand when this will be, see “Autorelease Pools”).
Does the method objectAtIndex: begin with "alloc"? No. Does it begin with "new"? No. Does it begin with "copy" or "mutableCopy"? No. Have you sent retain to the returned object? No.
Therefore you do not own nameString. Therefore you must not release or auto release it.
Sorry if the above seems a bit "leading by the nose" but when I first started with Objective-C, I found it useful to pretty much go through all the above in my head in exactly that way, otherwise I tended to get it wrong. It doesn't take long for it all to become second nature.
I think you don't totally get the "pointer" concept yet. Your variable nameString is just a pointer. Not a string.
In the line :
NSString *nameString = [myNewArray objectAtIndex:2];
You just assign the pointer to the actual memory address of the second object of the array. That's all.
If you are about to keep this object alive (even if the array will be deallocted), you better retain that object.
NSArray *myNewArray = [[NSArray alloc] initWithObjects:.......];
NSString *nameString = [myNewArray objectAtIndex:2]
[myArray release];
That's it, no need to bother any more with it. NSString will be released by environment itself.
There is no need to allocate or initialize NSString object and after all if you are not allocating any memory then there is no need to release....Only release NSArray objects nothing else....
You are going through right way...
There is no need to release the nameString.You only release when you are using(alloc”, “new”, “copy”, or “mutableCopy”) .
NSArray *myNewArray = [[NSArray alloc] initWithObjects:.......];
and getting value in NSString from any of index wont affect memory ...no need to allocate here.
The collected NSString need not required to be retained until you are passing its ownership to another controller/object.
When a method returns an object that is taken from and NSMutableArray does the object must be autoreleased? Check the following method. Also should I autorelease the nil value?
-(NSObject*)getElementByID:(NSString*)ID{
for(int i=0;i<[elements count];i++){
NSObject *element = (NSObject*) [elements objectAtIndex:i];
if([element.key isEqualToString:ID]){
return [element autorelease];
}
}
return nil;
}
You must not autorelease element because you are not an owner of it (you have not put a retain on it). You would have become an owner of it if you acquired it using alloc, new or retain. Since you acquired this object calling objectAtIndex:, you do not own it. See Three Magic Words. Calling autorelease here will cause a crash later do to over-release.
Your method name is incorrect and breaks KVC. A method that begins with get must take a pointer that will be updated with the result. This should be elementForID:. As noted above with the three magic words, naming in ObjC is very important to writing stable code
As a side note, it is traditional to use id is most cases rather than NSObject*. They mean slightly different things, but typically id is correct.
You never need to do any memory management related things to nil. So, no, you should not send autorelease to nil.
You also should not need to send autorelease to the element object that you are returning from your elements array. That object you are returning will remain in memory by virtue of elements itself having retained it. If the calling method would like to retain the value that you return, it may. But if that calling method only uses the returned value within its own scope, it is safe for it to do so without retaining it.
I have an array of dictionaries, which works ok. I am trying to track down a memory access issue and want to know:
If I create autoreleased strings for the dictionary, for example one string is from:
NSArray *dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error];
for (NSString *file in dirContents)
When I do
NSDictionary *dictItem = [NSDictionary dictionaryWithObjectsAndKeys:file, #"file"...
Does the resulting dictItem retain the individual strings? I have been assuming so ;-)
And then I add that dictItem to an array. I assume the addObject call on NSMutableArray will retain the dictItem for me...
What about when it comes time to free up the memory?
If I simply call removeAllObjects on the array (which crashes now), will it release all of the strings inside the dictionaries as well as the dictionaries themselves?
Hope this is somewhat understandable ;-)
thanks!
Here's a quick whistle-stop tour of memory management in Cocoa collections...
NSDictionary does not retain keys. Instead it creates a copy of the key. In other words adding an object as a key in a dictionary will not increment its retain count.
NSDictionary will retain the values for the keys that you pass it.
When you release (and eventually dealloc) the NSDictionary it is responsible for calling release on the objects it has stored (not you!)
NSArray will retain any object you add to it
NSArray will release all objects it holds a reference to when it is deallocated
Knowing the above...
dicItem will not retain your key #"file" - it will copy it
dicItem will retain your object called file
when dicItem is deallocated it will call release on its copy of #"file" and file
when you add a dicItem to your array it will be retained
when you release your array and it is deallocated all the dicItems it holds will be sent a release message
releasing your array should subsequently trigger a dealloc of your dicItem objects - provided they are referenced elsewhere (i.e. leaked)
you do not need to send your NSArray object a removeAllObjects message - the array itself will clean up after itself.
I think you are making this a little more complicated than it has to be. The only memory management you need to really worry about is within your own classes. When adding to an NSArray it does in fact retain the object, and then when you call removeAllObjects or the array is destroyed, it will release all of it's contained objects. However, this is where the concept of "owning" an object is important. When any object gets a reference to an object, it can call "retain" on it to indicate that it owns the object (this also applies to allocating a new object or using the "new" operator). That means, the object knows for sure the object will be around until it is done with it. To indicate that it is done with the object, it should always release or autorelease the object and set the reference to nil.
So bottom line, if you do not call retain, alloc, or new on an object, you should never call release. If you do call one of those functions, you should ALWAYS call release or autorelease on it. For any other object that you may send a reference to, you can assume that it will take ownership of it if it wants and if it does, it will always release it when it is done.
There are a few concepts about iPhone memory management that have got me confused, so I was hoping that someone could clarify these.
(a) Say that I am calling a function which returns an image, and I want to store that returned image in a variable so that I can assign it to various other variables without having to re-call the image generation function each time. At the moment I am doing the following:
UIImage *storedImage = [someFunction returnImage];
and because the storedImage is not alloc'ed I am not releasing the variable.
However, should I be explicitly alloc'ing and releasing the UIImage instead?
UIImage *storedImage = [[UIImage alloc] init];
storedImage = [someFunction returnImage];
...do stuff...
[storedImage release];
What is the implication of doing the direct assignment without alloc rather than alloc'ing the variable and then assigning?
(b) In the init method for various classes I am setting up the instance variables. At the moment I am doing the following:
self.arrayVariable = [[NSMutableArray alloc] init];
However, I have seen others do the assignment this way:
theArrayVariable = [[NSMutableArray alloc] init];
self.arrayVariable = theArrayVariable;
[theArrayVariable release];
or
theArrayVariable = [[NSMutableArray alloc] init];
arrayVariable = theArrayVariable;
[theArrayVariable release];
...which is the same as above, but without the self.
What is the difference between the three methods and which is better to use?
Regarding returning objects from methods, you should always return an autoreleased object from any method which does not begin with the name alloc, new, or contains copy. This is defined in Apple's object ownership policy, which states that you own any object that you create ("create" is defined as an object which you sent retain to, or used any of the aforementioned messages to retrieve an object), and that you are responsible for relinquishing ownership of that object by sending it the release or autorelease message.
The first method using self uses the property setter to set the instance variable to the argument (in this case whatever is on the RHS of the assignment).
This will do whatever you specified in your #property declaration (for example if you specified retain, the setter will retain the new value and release the old value).
The second method sets up a pointer to an NSMutableArray and passes it off to your property setter via self, which will most likely retain it, thereby bringing the reference count up to 2, since the object was previously alloc-ed, so you need to release it after this line to bring it back down to 1.
The third method will not work, because you are releasing an object with a reference count of 1 at the point of invoking release. How so you ask? Well, the first line sets up a pointer to an alloc-ed object, then directly assigns it to your instance variable, which will just point the ivar to the same object that theArrayVariable is pointing to. Then, that same object that theArrayVariable is pointing to gets sent the release method, which will effectively bring down the reference count of your ivar as well as the receiver, to 0. At this point both your instance variable and theArrayVariable will get deallocated.
a) The general rule for objective-c is that if you alloc it you must release it. In the first example, the method is returning a pointer to an object that already exists, and therefore you are not responsible for releasing it. In the second example, the first like is pointless since you aren't using allocated memory for stored image. This may cause a memory leak.
b) The first two are just stylistic differences, with no difference in outcome. In those, you will be left with arrayVariable pointing to the object returned by [[NSMutableArray alloc] init]; (assuming you have retain in the #property declaration) and you should release it in the -dealloc method. As stated above, the third will not work because you are merely passing off the pointer.
Here is a useful article for understanding obj-c memory management: http://memo.tv/memory_management_with_objective_c_cocoa_iphone
a) The code you gave does not do what you want. When you say
UIImage *storedImage = [someFunction returnImage];
someFunction returns an image object to you, but it does not guarantee that the image object will live forever. If you do not want the image to be freed without your permission in a future time, you should own it by calling retain like this:
UIImage *storedImage = [[someFunction returnImage] retain];
So now, this image object is owned by both someFunction and you. When you finish your work with this object you release it by calling release. When both someFunction and you call release for this object, it will be released (Of course if it is not owned by another owner).
In the other code segment, you create an image object and own it by calling
UIImage *storedImage = [[UIImage alloc] init];
But then you lose its reference by assigning a new object to the storedImage pointer by calling someFunction. In this situation the image created by you is not freed but continues to live somewhere in the memory.
I'm new to memory managed code but I get the idea pretty well.
On taking my app through the leaks tool in XCode, I noticed I only had to clean up my custom objects, but not dynamically created arrays for example, so I figured those data types are autoreleased - makes sense since I only had to release the arrays I used as properties that had a (retain) on them.
Then I noticed something peculiar : I was getting a leak on a certain array initialized like this :
NSMutableArray *removals = [NSMutableArray new];
but not a similar one
NSMutableArray *removals = [NSMutableArray arrayWithCapacity:9];
Now, the reason one was set up with "new" is that it could have 0-99 items in it, whereas the other one I knew was going to always be 9. Since both arrays are passed to the same method later based on user interaction, I was either getting a leak if I did not release at the end of the method, or an exception if I did!
I changed the first array to
NSMutableArray *removals = [NSMutableArray arrayWithCapacity:99];
and I get no leaks and don't have to release anything. Can anyone explain?
As noted in the memory management rules, whenever you have an object that you have created with +alloc, +new, -copy, or -mutableCopy, you own it and are responsible for releasing it at some point. (In fact, +new is just shorthand for [[MyClass alloc] init].) As you noted, creating an array via [NSArray new] without releasing it is a memory leak. However, if you handle this object properly, it is usually possible to release it at some point. For example:
If the method that uses the array is called from within the method that creates the array, then you should be able to release the array after it has been used. If the inner method needs to keep a more permanent reference to the array around, then that method is responsible for sending -retain and, eventually, -release to the object. For example:
- (void)myMethod {
NSArray *removals = [NSArray new];
// ...
[someObject someOtherMethod:removals];
[removals release];
}
If you created the array in an -init method for an object, then the -dealloc method can release it when the object is destroyed.
If you need to create the array and then return it from the method, you've discovered the reason that autoreleasing was invented. The caller of your method isn't responsible for releasing the object, since it isn't an +alloc, +new, -copy, or -mutableCopy method, but you need to ensure it is released eventually. In this case, you manually call -autorelease on the object before you return it. For example:
- (NSArray *)myMethod {
NSArray *removals = [NSArray new];
// ...
return [removals autorelease];
}
When you create the array via +arrayWithCapacity:, you aren't calling one of the "special" methods, so you do not have to release the result. This is probably implemented with -autorelease, much like the last example above, but not necessarily. (Incidentally, you can also create an empty autoreleased NSMutableArray with [NSMutableArray array]; the method is found in NSArray, so it won't show up in the documentation under NSMutableArray, but it will create a mutable array when sent to the NSMutableArray class.) If you're going to be returning the array from your method, you can use this as shorthand for [[[NSMutableArray alloc] init] autorelease]—but it is just a shortcut. In many situations, though, you can create an object with -init or +new and manually release it at the appropriate time.
This is how things implemented behind the scene:
+(NSMutableArray*) new
{
return [[NSMutableArray alloc] init];
}
and
+(NSMutableArray*) arrayWithCapacity:(NSNumber)capacity
{
return [[NSMutableArray alloc] initWithCapacity:capacity] **autorelease**];
}
In first case the array is allocated only and you're responsible for de-allocating it. In contrary the arrayWithCapacity has autoreleased for you and won't cause leak even you forget to deallocate.
Cocoa uses certain naming conventions. Anything that starts with alloc, new, or copy returns something with a retainCount of 1 and you are required to release. Anything else that a function returns has a balanced retainCount (it might be held by something else, or it might be retained and out released).
So:
NSMutableArray *removals = [NSMutableArray new];
Has a retainCount of 1, and:
NSMutableArray *removals = [NSMutableArray arrayWithCapacity:99];
or
NSMutableArray *removals = [NSMutableArray array];
Don't since the methods are not prefixed with alloc, new or copy. This is all spelled out in the memory management documentation. In particular:
You take ownership of an object if you
create it using a method whose name
begins with “alloc” or “new” or
contains “copy” (for example, alloc,
newObject, or mutableCopy), or if you
send it a retain message. You are
responsible for relinquishing
ownership of objects you own using
release or autorelease. Any other time
you receive an object, you must not
release it.