Retaining an autoreleased object is causing memory leak - objective-c

I am collecting response into the variable
-(NSMutableDictionary *)getCombineIdAndNames{
NSMutableDictionary *lObjCombineIdAndNamesArrayPtr = [[NSMutableDictionary alloc] init];
[lObjCombineIdAndNamesArrayPtr setObject:lObjtempNamePtr
forKey:lObjtempIdPtr];
return [lObjCombineIdAndNamesArrayPtr autorelease];
}
This is causing memory leak
gObjAppDelegatePtr.m_cObjCombineIdNameDictPtr = [gObjAppDelegatePtr.m_cDbHandler getCombineIdAndNames];
gObjAppDelegatePtr.m_cObjCombineIdNameDictPtr. That is a property of type copy. But it still giving memory leak. How to fix it.Please help me.

The getCombineIdAndNames is perfectly fine. You are allocing the dictionary and autoreleasing it before you return. Nothing wrong there.
This would suggest to me that the memory leak is being caused by the gObjAppDelegatePtr instance. Either it isn't releasing its property or maybe the whole object is being leaked.
As an aside, one thing you could improve in getCombineIdAndNames is to use the convenience constructor of NSMutableDictionary to avoid all alloc/release calls completely. You can also use the new Obj-C container syntax:
-(NSMutableDictionary *)getCombineIdAndNames{
NSMutableDictionary *lObjCombineIdAndNamesArrayPtr = [NSMutableDictionary dictionary];
lObjCombineIdAndNamesArrayPtr[lObjtempIdPtr] = lObjtempNamePtr;
return lObjCombineIdAndNamesArrayPtr;
}

Related

When to use Self?

I am new to iOS development.
I have property as follows,
#property(nonatomic,retain)NSMutableArray *dataArray;
I am doing the following, to alloc it
self.dataArray=[[NSMutable alloc]init];
In the dealloc I am doing the following
-(void)delloc{
[dataArray release];
[super dealloc];
}
But I am getting memory leak for my array initialization.However , it doesn't create the
leak when I don't use self. But I wonder is it a write approach to initialise the array
without using self. Any help is appreciated.
You're getting a leak because the dataArray property is declared with retain, which means that when you use self (thus you use the setter), your retain count goes up to 2 and you only release it once. On the other hand, if you only use the ivar, the retain count is 1 (because of alloc) and you release it once, which is fine. To avoid the memory leak in the first situation, autorelease it like this.
self.data = [[NSMutableArray alloc] init] autorelease];
That will balance the retain count. As for access, except for inside the dealloc method, try to use self (setter and getter)
You should read the memory management docs, first thing to start with when developing for Cocoa Touch.
Also, why don't you use ARC?
If you use the self. signature you are accessing to the object via automatically generated / custom getter/setter. The setter will tipically manage the memory and you don't need to do that.
If you don't use self you access directly to the object.
The code what you presented is leaking, because the default setter of the dataArray will retain to the array, what you set with self.dataArray = [[NSMutableArray alloc] init];
The correct usage is:
self.dataArray = [[[NSMutableArray alloc] init] autorelease];
or:
_dataArray = [[NSMutableArray alloc] init];
What's happening here is that alloc is adding one to the retain count of the new object. The property reference is also retaining the object. If you want to do it this way, you only want one of those. A common method is:
self.dataArray = [[[NSMutableArray alloc]init] autorelease];
However, better still is to use ARC as #c.cam108 suggested and avoid the whole problem.

Memory leak false positive

I have a simple method in my model to create a NSDictionary object containing its properties.
Unfortunately this method is seen by "Analyse" to be leaking memory :
Potential memory leak of an object allocated on line 76 (marked here with a dot) and stored in 'dic'.
-(NSDictionary*) getDictionary {
NSDictionary *dic = [[NSDictionary alloc] init];
[dic setValue:(id)self.internal_code forKey:#"internal_code"];
[dic setValue:(id)self.identifier forKey:#"id"];
[dic setValue:(id)self.owner forKey:#"owner"];
[dic setValue:(id)self.address forKey:#"address"];
[dic setValue:(id)self.displayed_name forKey:#"displayed_name"];
return dic;
}
I am not using ARC.
PS : To people coming in, the original code I posted was correct — it had an autorelease. I edited it after so the memory leak would reappear and to ask precisely why.
When returning an object from a method that doesn't begin with alloc, copy, mutableCopy or new, that object must be returned as autoreleased.
More conceptually, it should not be owned by your code when you return it. You take ownership of an object when you type alloc, copy, mutableCopy or new. You relinquish ownership when you type release or autorelease.
You can either change your return statement to:
return [dic autorelease];
Or better is to keep the alloc/init/autorelease all on one line so the code is easier to review, and the alloc and release cannot become separated by accident while copy and pasting code:
NSDictionary *dic = [[[NSDictionary alloc] init] autorelease];
An even easier way is to use this convenience constructor on NSDictionary:
NSDictionary *dic = [NSDictionary dictionary];
The above lines will fix the memory leak. However, you are also trying to mutate an immutable type (NSDictionary). You should be using a mutable dictionary instead:
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
Finally, you should ideally be setting values with the setObject:forKey: method, although setValue:forKey: will also work.
For more information on memory management, read the Advanced Memory Management Programming Guide.
If you are targetting iOS 4 or later, I would highly recommend using ARC.
Try to autorelease while returning the dic as below
return[dic autorelease];

NSCFArray not acting as NSArray

I'm trying to save data to and XML file on Iphone. For that, I load the wholeXML, add new data and the save it again. The problem arises when i try to store the new data, my
[mArray addObject:newData];
methods crashes, as mArray is not a NSMutableArray, instead, it is a NSCFArray even if I applied a mutableCopy method to it.
As I understand, a NSCFArray is a toll-free bridging to an NSArray, so I can't understand why the mutablyCopy method is not working.
Any idea??
NSMutableDictionary *wholeXML = [[NSMutableDictionary alloc] init];
wholeXML = xmlData;
NSArray *array = [[NSArray alloc] init];
NSMutableArray *mArray = [[NSMutableArray alloc] init];
array = [wholeXML objectForKey:#"Key"];
mArray = [a mutableCopy];
NSCFArray is a private subclass that gets instantiated when you do things with NSArray factory methods or initializers. You're doing too many initializations. Try this simplified version:
NSMutableDictionary *wholeXML = [[NSMutableDictionary alloc] initWithDictionary:xmlData];
NSMutableArray *mArray = [[NSMutableArray alloc] initWithArray:[wholeXML valueForKey:#"Key"]];
NSCFArray is the concrete class for both NSMutableArray and NSArray. It sounds like you are simply mistaken about what kind of array you have. Since the code you posted is obviously not your real code (it won't even compile, and wouldn't exhibit the problem even if it did), it's impossible to tell at what point your program is assigning an immutable array to the variable. But that's what it sounds like is happening.
I will say (and please don't take this as a personal criticism — it's just an observation) that the code you posted suggests you don't have a strong grasp on how classes and object identity work. That's probably the root cause here.
All three of your variables you initialize with [[Something alloc] init], but then you immediately throw away the object and replace it with something else. This means the original object (NSMutableArray in this case) just gets leaked and the variable now contains the new object you have assigned. If that new object isn't an NSMutableArray, it won't magically be turned into one just because that's what the variable held before.

"componentsSeparatedByString" Memory leak

I am facing some strange memory leak in our existing iPad application,
Here is a function which gives memory leak in instrument
-(NSString *)retriveInfo:(NSString*)fromstring:(NSString*)searchstring
{
NSArray *arrRetrive = [fromstring componentsSeparatedByString:searchstring];
if([arrRetrive count]!=0){
if ([arrRetrive count]!=1){
NSString *strDisplayOrder = [arrRetrive objectAtIndex:1];
arrRetrive = [strDisplayOrder componentsSeparatedByString:#"<"]; //MEMORY LEAK
}
}
return [arrRetrive objectAtIndex:0];
}
Here is a input parameter
Param 1 : <displayorder>1</displayorder><filename>201103153_0100.pdf</filename><title>【1面】東日本巨大地震直撃、日経平均一時675円安[br]原発関連売られる、東電はS安</title><category>トップ・注目株</category><dirpath>/var/www/mssite/webapp/data/pdf/20110315</dirpath><TimeStamp>201103141700</TimeStamp><FirstPageImg>20110315top.png</FirstPageImg></pagedata>
Param 2: <displayorder>
Basically i want to found (parse) value between start and end tag.
(I know NSXMLParser class but asper i explain this one is existing code and if i changed in code its too much time consuming)
Any suggetion?
With Regards
Pankaj Gadhiya
The code you've posted doesn't look like it's leaking memory -- all the methods you're calling are of the autorelease type (i.e. there's no new, alloc, copy, or retain in the code).
It's probably the code you have that calls retrieveInfo and does something with the result that's leaking memory (e.g. overretaining it). The leaks tool is pointing you at the componentsSeparatedByString because that's where the memory was allocated which was eventually involved in a memory leak.
Can you show us how you call retrieveInfo and what you do with the result?
Btw, what's the point of this nested if?
if([arrRetrive count]!=0){
if ([arrRetrive count]!=1)
It's wasteful, you might as well write this and get the same effect:
if ([arrRetrive count] > 1)
That leak probably means that you're over-retaining the return value. And leaks-tool just shows you the place where it was created.
You are leaking the NSArray when you re-assign a new NSArray inside the if block. The pointer to the original array is lost, which means that the runloop cannot release the memory allocated for the first result. The memory allocated for the second result is released.
You should really use a proper parser... however to address the leak, the following will work.
-(NSString *)retriveInfo:(NSString*)fromstring:(NSString*)searchstring
{
NSArray *arrRetrive = [fromstring componentsSeparatedByString:searchstring];
NSString *result = nil;
if([arrRetrive count]!=0){
if ([arrRetrive count]!=1){
NSString *strDisplayOrder = [arrRetrive objectAtIndex:1];
result = (NSString *)[[strDisplayOrder componentsSeparatedByString:#"<"] objectAtIndex:0];
}
}
return result;
}
What do you do with the object that's returned by this method? [arrRetrive objectAtIndex:0] is likely what's being leaked.
Leaks indicates that line with componentsSeparatedByString: because that's where the strings in the array are allocated. But the array isn't leaked.
Go into Leaks, look at a leaked instance, and click that little arrow button. You'll see all the retains and releases of the leaked object, which should point you to the problem.

How to release an object from an Array?

I am currently working on an demo app so I was a little sloppy how to get things done, however I run the "Build and Analyze" to see how many leaks I get,... well and there are a lot.
Source of teh proble is that I have a NSMutableArray and I add some Objects to it :
NSMutableArray *arr = [[NSMutableArray alloc] init];
[arr addObject:[[MyObject alloc] initWithText:#"Option1"]];
// I have like 100 lines like that and 100 complains
Now, xcode complains about a potential leak.
Can someone give me some advice how to handle that ?
Thanks.
The problem is that you're allocating an instance of MyObject which you have a responsibility to release. When you pass it to the array, the array also retains the object, so now both you and the array have to release it. You can simply autorelease the object, and the array will keep it retained until you remove the object from the array or destroy the array itself.
[arr addObject:[[[MyObject alloc] initWithText:#"Option1"]] autorelease];
Replace
[arr addObject:[[MyObject alloc] initWithText:#"Option1"]];
with
[arr addObject:[[[MyObject alloc] initWithText:#"Option1"] autorelease]];
Most collections (arrays, dictionaries) own the objects added to them. And, since you’ve sent +alloc to MyObject, you also own the object that’s just been instantiated. As the memory management rules say, you are responsible for relinquishing ownership of objects you own. Sending -autorelease to the newly instantiated object will do that.