3

I'm having some trouble with a NSMutableArray. I'm sure i'm doing something wrong with the allocation of the NSMutableArray but it's not obvious to me being an iPhone newbie. When i run the code below i can add the object MyObject to the array objects_ and set the name etc. The NSLog displays the correct data.

But when i try to access the objects_ member from the function printObject i get a SIGABRT. Looks like the memory has been deallocated or something?

Any help appreciated.


@interface MyObject : NSObject {
    NSString *name;
}

-(void) SetName:(NSString*) name_str;
-(NSString*) GetName;

@end

@interface ObjectListViewController : UITableViewController {
    NSMutableArray* objects_;
}

-(void) initTableData;

@end

@implementation ObjectListViewController

- (void)initTableData {
    objects_ = [[NSMutableArray alloc] initWithCapacity:10];
    MyObject *obj = [MyObject alloc];
    [obj SetName:@"Test"];
    [objects_ addObject:obj];

    MyObject* testObj = (MyObject*)[objects_ objectAtIndex:0];
    NSLog([testObj GetName]);
}

- (void)printObject {
    MyObject* testObj = (MyObject*)[objects_ objectAtIndex:0];
    NSLog([testObj GetName]);
}

4
  • Well, for starters, you never define printObject in the @interface. Commented Sep 7, 2010 at 2:31
  • 1
    This code looks fine, so you're missing the problem code. Are you sure initTableData is being called? Is anything else possibly touching objects_ before printObject is called? A SIGABRT is unusual, esp if there's no message in the console. It's not a bad selector, and it's not an empty array, both of which would spit out useful debug info. Commented Sep 7, 2010 at 3:26
  • @quixoto: The code doesn't look fine. He never inits obj. Commented Sep 7, 2010 at 8:51
  • @JeremyP: True. Along with all the other points you mention in your answer. None of it solves the mystery of the SIGABRT though. :) Unless of course-- and I'm now willing to bet this is the case-- there is useful info in the debug console that the OP is not sharing with us. Commented Sep 7, 2010 at 14:46

4 Answers 4

3

We can eliminate the lack of an init call on MyObject as the cause of the crash as in this case it will be benign. Calling init on NSObject will just return self, so calling it in this case won't change the behaviour. So I don't think the first two answers here will make any difference:

An object isn’t ready to be used until it has been initialized. The init method defined in the NSObject class does no initialization; it simply returns self.

Chuck correctly points out that init is a fundamental step in object allocation and initialization and you should be calling it when you allocate MyObject.

I am not sure the third answer is correct either. I don't really see how adding synthesise on the objects_ array will make any difference. You haven't defined it as a property, and I don't really see why you would need to, given it is just data internal to the class.

The comment on the question Well, for starters, you never define printObject in the @interface. from eykanal doesn't really help you either, because you must be calling printObject internally, otherwise you wouldn't be hitting the crash.

Reading the through the code, I can't see an obvious error. The retain count on objects_ after initTableData finishes should be one, the retain count on the instance of MyObject should also be one. So I think there must be some other code that is releasing objects_ elsewhere?

I am assuming it is crashing on the objectAtIndex call? Is there any info in the console? What does the call stack look like?

Sign up to request clarification or add additional context in comments.

3 Comments

yeah, I have to agree that init is not necessary. +1 for that
Whether init performs a useful function in this particular case, it's still required by the language. You're probably right that it's not the culprit here, but it's still wrong to say that "you don't need to call init" (and also, that's a comment, not an answer). So -1 for spreading inaccurate information. developer.apple.com/mac/library/documentation/Cocoa/Conceptual/…
@Chuck I thought I had clarified that sentence with "despite it being good practice and you might want to do stuff in your MyObject init". I was eliminating the lack of init as the cause of the crash, which I think is a valid. Point taken however and I will try and clarify.
1
 MyObject *obj = [MyObject alloc];

should be:

 MyObject *obj = [[MyObject alloc] init];

Comments

0
    @interface ObjectListViewController : UITableViewController {
        NSMutableArray* objects_;
    }

   @property (nonatomic, retain) NSMutableArray *objects_;
   -(void) initTableData;
   -(void) printObject;

    @end

add the synthesize in the implementation

@implementation ObjectListViewController
@synthesize objects_;

1 Comment

Good idea, but not the problem.
0

Here are some issues in your code:

  • You never initialise your MyObj object. Although it inherits directly from NSObject and NSObject is documented to do nothing except return self, you never know if other stuff happens behind the scenes, so put it in just to eliminate the posssibility.
  • Your methods don't follow the normal naming conventions. method names should begin with a lower case letter and "get" should only be used when passing back data by reference through the parameters as in e.g. NSData -getBytes:length:. Your getter and setter should be -name and -setName: respectively. This may seem like a minor nitpick, but it'll help you later on if you start to use KVO and KVC.
  • Never do NSLog(someStringVariable) always NSLog(@"%@", someStringVariable). As you have it now, if the object's name contains a percent formatting sequence e.g. %@, %d, %s etc, your program will crash on the NSLog. However, this is not the cause of your current problem - it would be crashing on the NSLog in -initTableData
  • you don't need to cast the result of -objectAtIndex:

Having said all that, I can't see anything that would cause the particular issue you have. It may be that the getter or setter for the name in MyObject is incorrect. Please post them.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.