Jules
Jules

Reputation: 7776

Obj-C, Potential leak of an object allocated on line ... NSMutableArray alloc

I'm having some trouble tracking down this memory leak error Potential leak of an object allocated on line...

@interface BNPieChart : UIView {
@private
    NSMutableArray* slicePointsIn01;
}

m
- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self initInstance];
        self.frame = frame;        
        slicePointsIn01 = [[NSMutableArray alloc]
                       initWithObjects:nFloat(0.0), nil];       

- (void)initInstance {
    slicePointsIn01 = [[NSMutableArray alloc]
                       initWithObjects:nFloat(0.0), nil];

I did try adding a property / synthesize / dealloc for slicePointsIn01 however this gives me the same error.

What am I doing wrong ?

Upvotes: 1

Views: 538

Answers (1)

Chris Cooper
Chris Cooper

Reputation: 17584

slicePointsIn01 gets set to two different objects: one in initInstance, and then one again later in initWithFrame:.

Because the first one was set to an alloc'd object, then that object was never release before you changed the assignment, the original object gets leaked.

If you add a property, you need to make sure you're actually using it, and not using the instance variable directly. You would do that by doing assignments in one of the two following ways:

self.myProperty = //something;
[self setMyProperty: //something];

Note (thanks @André): make sure the something object has a retain count of 0 upon assigning (i.e. autoreleased, usually), because the property retains it for you.

//NOT like this:
myProperty = //something;

This line uses the instance variable directly. It causes your leak because without using the property, the reference count on the object pointed to is not altered.

Edit: You shouldn't ever check the retain count. Just follow the rules within each place you use the object, and you will be fine. Here are the rules:

  • You own any object you create by allocating memory for it or copying it, i.e. with the methods alloc, allocWithZone:, copy, copyWithZone:, mutableCopy, mutableCopyWithZone:

  • If you are not the creator of an object, but want to ensure it stays in memory for you to use, you can express an ownership interest in it by calling retain

  • If you own an object, either by creating it or expressing an ownership interest, you are responsible for releasing it when you no longer need it, by calling release or autorelease

  • Conversely, if you are not the creator of an object and have not expressed an ownership interest, you must not release it.

  • If you receive an object from elsewhere in your program, it is normally guaranteed to remain valid within the method or function it was received in. If you want it to remain valid beyond that scope, you should retain or copy it. If you try to release an object that has already been deallocated, your program crashes.

You don't have to write setMyProperty. When you @synthesize a property, that method is created for you.

Upvotes: 4

Related Questions