Confusing double free error message/memory leak in iPhone app
Asked Answered
S

3

1

EDIT - added .h file

I'm having difficulty trying to find the cause of a double free error.

Steps taken to solve

1) Used the Zombies tool. Zombies reports that tid is being double freed

2) Set a breakpoint on malloc_error_break. This identifitied the following code segment as faulty:

 - (void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:animated];

        [connection release];

        [ldestination release];
        [ldeparts_from release];
        [ltime release];
        [lcs_id release]; /// It breaks here


        [carsharexml release];
    }

3) I looked through the code to see where I had [lcs_id release] before - I found nothing.

4) In a desperate attempt to solve it I commented out [lcs_id release]. This stopped the double free error messages but when I ran it through leaks it said that this was causing memory leaks.

What am I doing wrong?

Thanks very much.

Below is a complete copy of the code:

#import <UIKit/UIKit.h>
#import "MyManager.h"

@interface ListOfCarShares : UITableViewController <NSXMLParserDelegate>
{
    NSURLConnection *connection;
    NSMutableData *carsharexml;
    NSMutableArray *ldestination;
    NSMutableArray *ldeparts_from;
    NSMutableArray *lcs_id;
    NSMutableArray *ltime;
    NSMutableString *currentElement;

    NSMutableString *tdest;
    NSMutableString *tfrom;
    NSMutableString *ttime;
    NSMutableString *tid;



}

-(void)fetchcarshares;

@property (nonatomic, assign) IBOutlet UITableViewCell *maincell;


@end


//
//  ListOfCarShares.m
//  Warwick_Culture
//
//  Created by Me on 26/10/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "ListOfCarShares.h"

@implementation ListOfCarShares

@synthesize maincell;

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}



- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI
 qualifiedName:(NSString *)qualifiedName
    attributes:(NSDictionary *)attributeDict
{
    currentElement = [[elementName copy] autorelease];
    if ([elementName isEqualToString:@"destination"]) 
    {

        //NSLog(@"found current conditions tag it reads %@",currentElement);
        tdest = [[NSMutableString alloc] init];
    }

    if ([elementName isEqualToString:@"departs_from"])
    {
        tfrom = [[NSMutableString alloc] init]; 
    }


    if ([elementName isEqualToString:@"time"])
    {
        ttime = [[NSMutableString alloc] init]; 
    }

    if ([elementName isEqualToString:@"cs_id"])
    {
        tid = [[NSMutableString alloc] init]; 
    }



}




- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{

    if ([currentElement isEqualToString:@"destination"])
    {

        [tdest appendString:string];
    }

    if ([currentElement isEqualToString:@"departs_from"])
    {

        [tfrom appendString:string];
    }

    if ([currentElement isEqualToString:@"time"])
    {

        [ttime appendString:string];
    }

    if ([currentElement isEqualToString:@"cs_id"])
    {

        [tid appendString:string];
    }

}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName 
  namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{

    if ([currentElement isEqualToString:@"destination"])
    {

        [ldestination addObject:tdest];
        [tdest release];

    }

    if ([currentElement isEqualToString:@"departs_from"])
    {

        [ldeparts_from addObject:tfrom];
        [tfrom release];
    }

    if ([currentElement isEqualToString:@"time"])
    {

        [ltime addObject:ttime];
        [ttime release];
    }

    if ([currentElement isEqualToString:@"cs_id"])
    {

        [lcs_id addObject:tid];
        [tid release];
    }



}





- (void)didReceiveMemoryWarning
{

    [super didReceiveMemoryWarning];


}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
}

- (void)viewDidUnload
{
    [super viewDidUnload];

}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    ldestination = [[NSMutableArray alloc] init];

    ldeparts_from = [[NSMutableArray alloc] init];
    ltime = [[NSMutableArray alloc] init];
    lcs_id = [[NSMutableArray alloc] init];
    carsharexml = [[NSMutableData alloc] init];

    [self fetchcarshares];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    [connection release];

    [ldestination release];
    [ldeparts_from release];
    [ltime release];
    [lcs_id release]; ///


    [carsharexml release];
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];


}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{

    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return [ltime count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
    if (cell == nil) 
    {
        [[NSBundle mainBundle] loadNibNamed:@"carsharecell" owner:self options:nil];

    }

    // Configure the cell...
    cell=maincell;

    UILabel *from;
    UILabel *dest;
    UILabel *time;

    from = (UILabel *)[cell viewWithTag:4];
    dest = (UILabel *)[cell viewWithTag:5];
    time = (UILabel *)[cell viewWithTag:6];


    from.text=[ldeparts_from objectAtIndex:indexPath.row];
    dest.text=[ldestination objectAtIndex:indexPath.row];
    time.text=[ltime objectAtIndex:indexPath.row];


    return cell;
}

/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the specified item to be editable.
    return YES;
}
*/

/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }   
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }   
}
*/

/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/

/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the item to be re-orderable.
    return YES;
}
*/

-(void)fetchcarshares
{

    MyManager *sharedManager = [MyManager sharedManager];




    NSString *urlString = [NSString stringWithFormat:@"http://url/get.php?username=%@&password=%@",sharedManager.user,sharedManager.passw];

    NSURL *url = [NSURL URLWithString:urlString];
    NSURLRequest *req = [NSURLRequest requestWithURL:url];

    connection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];


}

-(void) connection:(NSURLConnection *)conn didReceiveData:(NSData *)data
{
    [carsharexml appendData:data];
}


-(void) connectionDidFinishLoading:(NSURLConnection *)conn
{
    NSString *xmlcheck = [[NSString alloc] initWithData:carsharexml encoding:NSUTF8StringEncoding];

    NSLog(@"%@",xmlcheck);

    [xmlcheck release];






    NSXMLParser *parser = [[NSXMLParser alloc] initWithData: carsharexml];

    [parser setDelegate:self];

    [parser parse];

    [parser release];








    [[self tableView] reloadData];




}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 102;
}



#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

}

-(void)dealloc
{
    [super dealloc]; 
}

@end
Simplehearted answered 19/11, 2011 at 3:41 Comment(3)
how is tid defined in the header?Schluter
It's useful to note that when a mutablearray is released, it calls release on the objects in it. For that reason, another place to look is the items that ever get into that array (tid). If those are ever released or autoreleased for any reason, then one of those items could be double freed.Schluter
opposite problem in this link but might be worth a read: #2053904Schluter
C
0

Try this....

- (void)viewWillAppear:(BOOL)animated
  {
    [super viewWillAppear:animated];

    ldestination = [[[NSMutableArray alloc] init]retain];

    ldeparts_from = [[[NSMutableArray alloc] init]retain];
    ltime = [[[NSMutableArray alloc] init]retain];
    lcs_id = [[[NSMutableArray alloc] init]retain];
    carsharexml = [[[NSMutableData alloc] init]retain];

    [self fetchcarshares];
 }
Chainsmoke answered 19/11, 2011 at 5:4 Comment(2)
I have had the exact same code before and none of these problems... why is this different?Simplehearted
you shouldn't need to retain objects that are alloc, init'd. alloc init means you own it and it has a retain count of 1. If you do this, you're likely not finding the real root issue, just papering over it by over retainingSchluter
C
0

if lcs_id property not define as retain you need to replace the line

 lcs_id = [[NSMutableArray alloc] init];

to

lcs_id = [[[NSMutableArray alloc] init] retain];

or another work around would be in

- (void)viewWillDisappear:(BOOL)animated
    {
       if(lcs_id)
       {
              [lcs_id release];
              lcd_id = nil;
       }
}
Crossness answered 19/11, 2011 at 5:15 Comment(4)
you shouldn't need to retain objects that are alloc, init'd. alloc init means you own it and it has a retain count of 1. If you do this, you're likely not finding the real root issue, just papering over it by over retainingSchluter
but if property is not defined as retain that that will be deallocated as soon as control goes out of the function as it would be assigned locally ...Crossness
No - alloc will give it a retain count of 1. Only auto released objects will get released at some point in the near future when the run loop processes. It will not release an object that has not been auto released.Schluter
Check out rule #1 in memory guide - you own anything created from alloc, copy or mutable copy and must explicitly release.Schluter
A
0

For the Crashing issue, please check below point 1. Please make sure you haven't use [autorelease] for object lcs_id 2. Most important, if you have use same variable in other pages in application, you have received above error.

please try

[this.lcs_id release] Your error will resolved.

Affright answered 19/11, 2011 at 14:30 Comment(1)
it would be self and that would only be needed if lcs_id was a property (which it's not based on your code - just an iVar). Please confirmSchluter

© 2022 - 2024 — McMap. All rights reserved.