EXC_BAD_ACCESS when debugging

1

I'm getting this error when trying to see the contents of a NSMutableArray:

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00000021
0x94d5a688 in objc_msgSend ()

ViewController.h:

@interface PeopleViewController : UITableViewController {
    NSMutableArray *people;
}

@property (nonatomic, retain) NSMutableArray *people;

ViewController.m:

@implementation PeopleViewController

@synthesize people;

In viewDidLoad:

- (void)viewDidLoad {
    [super viewDidLoad];

    // initialize our people array with an autoreleased object
    people = [NSMutableArray array];

... Populate the people array with Person objects.

}

When I'm at the point where I'm modifying the contents of a cell in the tableview, I'm unable to access the people array in gdb when typing 'po self.people':

Person *person = [[Person alloc] init];
person = [self.people objectAtIndex: indexPath.row]; // <--- 'po self.people' called  
cell.textLabel.text = person.personName;

Any ideas why I can't access it?

iphone
objective-c
asked on Stack Overflow Jan 5, 2010 by LB.

3 Answers

7

The line

people = [NSMutableArray array];

returns an autoreleased array that will be released on the next iteration of the current run loop. You should retain that:

people = [[NSMutableArray array] retain];

and of course release it in your dealloc method.

However: Apple engineers have often mentioned in conferences to avoid autoreleased instances like this whenever possible in the iPhone, for performance reasons. Try using alloc/init instead:

people = [[NSMutableArray alloc] initWithCapacity:1];

with the corresponding release in the dealloc method. In this case you don't even need to retain (init returns an instance with a retain count of 1, which is what you need).

And justin's comment is correct: you should do this instead:

Person *person = [people objectAtIndex:indexPath.row];
cell.textLabel.text = person.personName;

and this should work.

answered on Stack Overflow Jan 5, 2010 by Adrian Kosmaczewski • edited Jan 6, 2010 by Adrian Kosmaczewski
4

is indexPath.row > [people count]?

Also, why are you doing this:

Person *person = [[Person alloc] init]

You're allocating memory, and then pointing to completely different memory.

answered on Stack Overflow Jan 5, 2010 by justin • edited Jan 5, 2010 by Jason Coco
1

You can avoid having to fuss with retaining properties by using the self notation to call the accessor and setter methods created by the @synthesize directive.

When you set the people property directly in viewDidLoad it sets the property but does nothing for memory management. However, if you set it with self.people you actually call the synthesized setter method that because of the retain setting of the @property directive will automatically retain the assigned array.

As an aside, I would recommend always using -[NSMutableArray initWithCapacity:] instead of a bare init. It is the actual initializer for the class. You can call it with just '1' if you don't know how big it will be. In the past, I have seen odd problem arise from just using bare init.

answered on Stack Overflow Jan 5, 2010 by TechZen

User contributions licensed under CC BY-SA 3.0