4

I have a very simple Person class that has a ivar called name ( an NSString). When I try to release this ivar in dealloc the static analyzer gives me a weird error:

Incorrect decrement of the reference count of an object that is not owned at this point by the caller

What am I doing wrong?

BTW, here's my code:

@interface Person : NSObject {

}

@property (copy) NSString *name;
@property float expectedRaise;

@end


@implementation Person

@synthesize name, expectedRaise;

-(id) init {
    if ([super init]) {
        [self setName:@"Joe Doe"];
        [self setExpectedRaise:5.0];
        return self;
    }else {
        return nil;
    }

}

-(void) dealloc{
    [[self name] release]; // here is where I get the error
    [super dealloc];
}

@end
cfischer
  • 24,452
  • 37
  • 131
  • 214

1 Answers1

18

You're releasing an object returned from a property getter method, which in many cases would be the indication of a possible bug. That's why the static analysis is picking it up.

Instead, use:

self.name = nil;

or:

[name release];
name = nil;
Darren
  • 25,520
  • 5
  • 61
  • 71
  • 4
    Preferably the latter. Apple recommends against using getters or setters in init and dealloc methods. – Chuck Nov 06 '10 at 00:16
  • 1
    You could also put it on one line separated by a comma `[name release], name = nil` – Abizern Nov 06 '10 at 05:40
  • @Chuck What's the reason for recommends against using getters or setters in init and dealloc? – cfischer Nov 06 '10 at 13:39
  • 2
    If there are observers or an override in a subclass that triggers behavior, it'll be triggered from `dealloc` which is pretty much never what you want (because the state of the object will be inconsistent). – bbum Nov 06 '10 at 19:03
  • The way I put it is, don't send messages to a half-initalized or half-deallocated object. (Except messages that are explicitly indicated as safe for that—generally because you wrote them for that purpose, in which case they should probably be private and have their purpose documented.) – Peter Hosey Nov 07 '10 at 03:02
  • 1
    @bbum But why both `release` and `= nil` ? Shouldn't the first one suffice ? – Nicu Surdu Apr 29 '12 at 20:18
  • 2
    An old habit of defensiveness no longer needed under ARC. Without ARC, simply releasing `name` will leave the variable still referencing the [likely now former] object. If anything else were to message it, **BOOM**. If you want to be proactively defensive -- to find situations where you message `name` after it is released -- use `name = (id)0x1;`; that'll guarantee a crash. – bbum Apr 29 '12 at 22:42