views:

43

answers:

1

When my program gets to the line: [userNumSequence addObject:[NSNumber numberWithInteger: sequenceNumber]]; it gets the error: Program received signal: “EXC_BAD_ACCESS”.

All I'm wanting to do is to store an integer in the array.

//  JBNumberGeneration.m

#import "JBNumberGeneration.h"


@implementation JBNumberGeneration

- (id) init{ 
    if (self = [super init]){ 
        userNumSequence = [NSMutableArray arrayWithCapacity:0]; 
    } return self; 
}

-(IBAction)logSequenceNumber:(id)sender{
    NSString *titleOfButton = [sender title];
    int sequenceNumber = [titleOfButton integerValue];
    i=0;

    [userNumSequence addObject:[NSNumber numberWithInteger: sequenceNumber]];

    //int currentNum = [((NSNumber*)[userNumSequence objectAtIndex: i]) integerValue];
    //NSLog(@"%i", currentNum);

    int count = [userNumSequence count];
    NSLog(@"Array size: %i", count);

    i++;
}
@end

//  JBNumberGeneration.h

#import <Cocoa/Cocoa.h>


@interface JBNumberGeneration : NSObject {
    IBOutlet NSTextField *displayLabel;
    int randNum;
    int level;
    int i;
    NSMutableArray* userNumSequence;
}

-(IBAction)logSequenceNumber:(id)sender;
@end
+3  A: 

EXC_BAD_ACCESS usually occurs when you try to access a member that has already been deallocated. Because you are calling [NSMutableArray arrayWithCapacity:] in your init function, it may have already been released by the time logSequenceNumber:(id)sender is called. Try adding @property (nonatomic, retain) NSMutableArray* userNumSequence to your @interface and @synthesize userNumSequence to your @implementation. Then call self.userNumSequence = [NSMutableArray arrayWithCapacity:0] in your init method. Don't forget to set it to nil in dealloc.

EDIT: Also, just to be clear the Cocoa memory management naming standards are like this:

  1. If you call [[Object alloc] initSomehow], or [object retain] you are responsible for releasing it (calling init methods will automatically call retain).
  2. If you call methods like [Object objectWithSomething:something], these are usually autoreleased and will be released sometime in the future. You should never assume these exist beyond the scope in with they are created. According to the Cocoa documentation, scope includes the call stack. If a: calls b: which calls c:, and c: returns an autoreleased object, it can be passed safely all the way back up for a: to use. Beyond that it is released. This is at least my interpretation of the explanation of autorelease.

If you need to use something for the lifetime of your object, retain it when you get it and release it in dealloc.

Matt Baker
Thanks for the help, it worked perfectly.
JoeMBlair
No problem. Objective-C memory management can be a bit weird if you're not used to it.
Matt Baker
Sorry, you are wrong. init does not automatically call retain. Alloc has an implicit retain, not init. Also it is considered a bad idea to use properties in init. It's far better in this case just to alloc and init the array in init.
JeremyP
I mean, you are wrong on those two specific issues. You are correct that the array is not retained in the questioner's code and this is why it goes away.
JeremyP
@Jeremy. Good to know. I knew the [[alloc] init] call does retain, but I just took a stab and guessed init called retain. Also, why is it considered a bad idea to use properties in init? It's just a call to a setter that releases the current instance, retains the new one, and assigns it to the ivar.
Matt Baker
You can't be certain that the setter *just* releases the old value, retains the new value and sets the value to the new value. The setter is an Objective-C method and can potentially do anything it likes.
JeremyP
@Jeremy. Yes you are right, but in that case it would be safe to use the property if the getter and setter were both generated using @synthesize, correct? I do see your point that the setter could change at any time, however. At any rate, the important thing is that he retain the array instance. That was really my point with adding the retain property.
Matt Baker
No, not correct. A subclass or category could override the getter and setter even if they are synthesized. Anyway you are correct that the important thing is to make sure the array is retained.
JeremyP
Oh, good call. I'll keep that in mind in the future.
Matt Baker