unable to find possible memory leak - iphone

I having a warning when i analyze my code for memory leak from xcode. I tried for hour to figure it out but couldn't understand, but i have some suspicion on specific code:
[stack push:[outputString copy]];
[stack print]; //here xcode tell there is potential leak of an object that is createn on above line
and my stack implementation is:
-(void) push:(NSString *)element{
[store addObject:element];
top++;
}
-(void) print{
NSLog(#"%#", [store objectAtIndex:top]);
}
- (void)dealloc {
[store release];
[super dealloc];
}
and this is my init for my stack class:
-(id) initWithMutableArray{
self = [super init];
if(self){
store = [[NSMutableArray alloc] init];
top = -1;
}
return self;
}
My suspicion is on code [outputString copy]. But i am storing it on array and i am releasing store array on dealloc.
Gracias.

There is no release to balance the [outputString copy] so it is leaked. When adding the object to your array it gets retained by the array and released when the array is destroyed.

Related

Memory Management Headache

I get leaks if I dont put it in dealloc. I get a crash EXC_BAD_ACCESS If I do. I cannot see anything wrong with this code. The bad access is pointed at [events release]. Have I made a mistake in the code below or is Instruments just having a laugh at my expense?
events is an NSArray
#interface EventsViewController : UITableViewController
{
#private
NSArray *events;
}
- (void)viewDidLoad
{
events = [[self getEvents] retain];
}
- (void)dealloc
{
[events release];
[super dealloc];
}
- (NSArray*)getEvents
{
NSMutableArray *response = [[[NSMutableArray alloc] init] autorelease];
//Some sql
while(sqlite3_step(statement) == SQLITE_ROW)
{
Event *event = [[[Event alloc] init] autorelease];
event.subject = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)];
[response addObject:event];
}
return response;
}
Update
A lot of you are saying the code is fine which is a plus. I dont manipulate events elsewhere - I have removed any code that does to try and single out the crash. Perhaps its in the parent view?
This is the click event that pushes the EventsViewController:
- (void)eventsClick:(id)sender
{
EventsViewController *eventsViewController = [[EventsViewController alloc] initWithNibName:#"EventsViewController" bundle:nil];
eventsViewController.anywhereConnection = anywhereConnection;
eventsViewController.contact = contact;
[[self navigationController] pushViewController:eventsViewController animated:YES];
[eventsViewController release];
}
The crash is actually happening when I return to the parent view. (I think it is considered a parent in this scenario). But perhaps the [eventsViewController release] just triggers dealloc in the EventViewController.
Have you considered just refactoring your code to use ARC? It works with iOS 4 and up and will make your life a lot easier. There are plenty of tutorials out there that will guide you how to do it, and will remove the need to manually figure out the nuances of memory management.
If your Events object has property 'subject' set as assign, then the results of stringWithUTF8String: will not be retained. (Same thing if Events is a C++ object.)
The stringWithUTF8String: method returns an auto-released object that will be released at the next turn of the event loop.
There is a huge difference when you reference a variable via "self", and when you don't.
When you use
events = [[self getEvents] retain];
the memory allocated in getEvents never gets stored in the class property and is basically a leak.
You need to use
self.events = [self getEvents]; // no need to use retain if property is correctly defined.
Then
[events release];
should work fine.
try putting
events = nil;
in dealloc.

iphone: How to solve NSArray memory Leak?

I am releasing NSArray and NSMutableArray but its show memory leak. while ZoneData code is like this
-(ZoneData*) initWithZoneName:(NSString *)zoneNameIn SdName:(NSString *)sdNameIn eCount:(NSString *)eCountIn iCount:(NSString *)iCountIn StandLat:(NSString *)standLatIn StandLong:(NSString *)standLongIn
{
self = [super init];
if (self)
{
zoneName = [zoneNameIn copy];
lsdName = [sdNameIn copy];
leCount = [eCountIn intValue];
liCount = [iCountIn intValue];
standLat = [standLatIn copy];
standLong = [standLongIn copy];
}
return self;
}
how to solve this?
The problem is your instance variables. In your -init, you are correctly assigning them to copies of the strings from the array. However, you need t also release them in -dealloc.
-(void) dealloc
{
[zoneName release];
[lsdName release];
[standLat release];
[standLong release];
[super dealloc];
}
Now, you may be asking why the leaks tool is telling you the leaks are where you create the NSArray with the strings in it instead of the init method. The reason is that -copy for immutable objects is optimised to do nothing except send retain to self. So those copies you have as instance variables are in reality the same objects as was created by -componentsSeparatedByString:
componentsSeparatedByString: returns an autoreleased NSArray. You are not supposed to release that yourself, but the closest NSAutoreleasePool will do that for you. In line 61 you are overreleasing the array.
If you are concerned about the memory usage while performing the loop you can clear autoreleased objects in each iteration of the loop:
for (...)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// your loop contents.
[pool drain];
}

Leak in NSMutableArray

I have been pulling out my hair trying to figure out why this is leaking. In my .h file I have a synthesized property nonatomic, retained NSMutableArray. In my viewDidLoad I declare it as:
self.tableData = [[NSMutableArray alloc] init];
[self.tableData removeAllObjects];
fillData(self.tableData);
Throughout my application, I call [self.tableData removeAllObjects] and then repopulate it with the fillData(self.tableData) function. This function fills up the data from a static C++ string set:
void fillData(NSMutableArray* list)
{
for (set<string>::const_iterator itr = sortedData.begin(); itr != sortedData.end(); ++itr){
[list addObject:[NSString stringWithFormat:#"%s", ((string)*itr).c_str()]];
}
}
In my dealloc method I do:
[self.tableData removeAllObjects], [self.tableData release], tableData = nil;
Where did I drop the ball? Instruments says it's in the [list addObject....] line.
Thanks
self.tableData = [[NSMutableArray alloc] init];
[self.tableData removeAllObjects];
fillData(self.tableData);
+1 retain for alloc, +1 retain for using the property's setter. You haven't balanced the +1 from alloc. If you are going to use the setter:
self.tableData = [NSMutableArray array];
fillData(self.tableData);
Note that removeAllObjects in that is completely pointless.
This is odd, too:
[self.tableData removeAllObjects], [self.tableData release], tableData = nil;
First, don't bother removing the objects. When the array is deallocated, it'll release all objects. Secondly, using the setter to call release and then immediately do a direct assignment is inconsistent. Either do:
self.tableData = nil;
Or:
[tableData release], tableData = nil;
(Note that the use of the , in all of this is also purely for your benefit -- it has no impact on generated code.)
Also, use stringWithUTF8String: and not stringWithFormat:.
Not sure if it's the leak, but this looks like it's a problem:
self.tableData = [[NSMutableArray alloc] init];
You say that tableData is a property that's retained. Try:
self.tableData = [NSMutableArray arrayWithCapacity:10];
That way the property retains it and the array itself is autoreleased. Your release in dealloc will bring the retain count back down to zero.
The problem is that your property is set as retain, and you set it to an already retained object.
You should do it like this:
// viewDidLoad
NSMutableArray *array = [[NSMutableArray alloc] init];
self.tableData = array;
[array release]; // this is important
// dealloc
self.tableData = nil; // will automatically release the array
In your dealloc, you use properties which retain the tableData again. That is not really what you want, so do:
[tableData release];
or
[self->tableData release]; // not necessary, but some prefer it.
or
self.tableData = nil; // property will handle release
No need to clear the tableData, no need to set anything to nil (you are deallocating, so nothing will access it anymore).

iPhone - Objective-C - Memory Leak with initWithArray

I am using the code below to set my two NSArray ivars:
The issue is, I keep getting a memory leak on the following lines:
followingFriendsArray = [[NSArray alloc] initWithArray:friend.Following];
followerFriendsArray = [[NSArray alloc] initWithArray:friend.Followers];
Is this not the correct way to set ivars from an existing NSArray of items? Any help would be appreciated. I've also tried to autorelease the above two lines, but when I actually access them in another method I get an error that they've already been released.
I have included my Interface and Implementation code below:
Interface .h:
NSArray *followingFriendsArray;
NSArray *followerFriendsArray;
#property (nonatomic, retain) NSArray *followingFriendsArray;
#property (nonatomic, retain) NSArray *followerFriendsArray;
Implementation .m:
- (void)handlerGetFollowingInformation:(id)value {
BOOL success = [Utility checkWebServiceErrors:value controller:self.navigationController];
if (success) {
Friend *friend = (Friend *)value;
followingFriendsArray = [[NSArray alloc] initWithArray:friend.Following];
followerFriendsArray = [[NSArray alloc] initWithArray:friend.Followers];
}
}
This is how I need to access the arrays:
- (void)followersButtonTapped:(id)sender {
FollowingVC *fvc = [[FollowingVC alloc] initWithNibName:#"FollowingViewController" bundle:nil];
fvc.friends = followerFriendsArray;
[self.navigationController pushViewController:fvc animated:YES];
[fvc release];
}
I release my two ivars in the following way as per usual:
- (void)viewDidUnload {
self.followingFriendsArray = nil;
self.followerFriendsArray = nil;
[super viewDidUnload];
}
- (void)dealloc {
[followingFriendsArray release];
[followerFriendsArray release];
[super dealloc];
}
I mean the code works just fine, it's just that I'm concerned about said memory leaks when I run the "Leaks" performance tool.
OK
you should not use autorelease in this case, but you have to release the arrays by calling :
[followingFriendsArray release];
[followerFriendsArray release];
you can do it:
when you don't need to use them any more.
in the dealloc method in your .m file.
option 2looks like that -
- (void)dealloc {
[followingFriendsArray release];
[followerFriendsArray release];
[super dealloc];
}
BTW -
if you don't manipulate the arrays after creating them (add / remove objects) you should use an immutable array (NSArray).
Good Luck
Your method handlerGetFollowingInformation is assigning new values to followingFriendsArray and followerFriendsArray without releasing the previous contents. If you call this method more than once on the same instance you will leak.
CRD is right that the arrays are not released inside the handlerGeFollowingInformation method but the fix is maybe overkill. What you need to do is to use self. so that the setter method is called which does that automatically. You could should look like this:
- (void)handlerGetFollowingInformation:(id)value {
BOOL success = [Utility checkWebServiceErrors:value controller:self.navigationController];
if (success) {
Friend *friend = (Friend *)value;
self.followingFriendsArray = [[NSArray alloc] initWithArray:friend.Following];
self.followerFriendsArray = [[NSArray alloc] initWithArray:friend.Followers];
}
}
Easy fix but hard to spot and I ran into this issue over and over again especially when I started to dealloc are the properties.
-Andy

Objective C: Memory Leak of Dictionary used in singleton

I am using a singleton class to share data between views in my iphone app. My singleton class contains a dictionary which I allocate in my -init method:
- (id)init
{
if ( self = [super init] )
{
self.dataList = [[NSMutableDictionary alloc]init];
}
return self;
}
I release it in my dealloc method:
- (void)dealloc
{
[dataList release];
[super dealloc];
}
This dataList is downloaded from a server, and I do this multiple times in my app,so I have a custom setter method to release the old one, and retain the new one:
-(void) setDataList:(NSMutableDictionary*)d
{
if( dataList !=nil){
[dataList release];
dataList = [d retain];
else
dataList = [d retain];
}
ON using the leaks tool, I am getting a memory leak of the dictionary. I think I am doing the alloc and release of the dictionary properly..does the leak occur because the dealloc method of the singleton is not getting called?
Thanks for your help,
Srikanth
Add an autorelease:
self.dataList = [[[NSMutableDictionary alloc] init] autorelease];
When you assign a an object to a property it retains it and whenever you call and init method it retains, bringing the retain count to 2.
It also releases when you reassign it so you can just
self.dataList = newValue;
#syntehsize'd properties take care of all the retain release stuff for you.