Don't get how have a not autorelease object in class definition

Discussion in 'iOS Programming' started by mamcx, Jan 8, 2009.

  1. mamcx macrumors regular

    Mar 13, 2008
    Hi, I have this:

    @interface Db : NSObject {
    	NSString *path;
    	FMDatabase* theDb;
    @property(readonly, retain) FMDatabase *theDb;
    @property (readonly, nonatomic) NSString *path;
    Then, I create:

    - (id)initWithName:(NSString *)name{
        self = [super init];
        if (self) {
            path = [name copy];
    		theDb = [[FMDatabase alloc] initWithPath:path];
    	return self;
    - (void)dealloc
        NSLog(@"Deallocating %@", self);
    	[theDb release]; <----FAIL!!!
    	[path release];
        [super dealloc];
    I don't understand why fail in the release part, if I say retain in the property. Happend the same thing if I put retain in the init.

    If I remove this line, I don't get a error, but that not sound rigth to me....
  2. robbieduncan Moderator emeritus


    Jul 24, 2002
    Have you synthesized the property accessors? Where do you use them? You should be using something like

    self.theDb = ...
    to actually use the accessors which have been synthesized...
  3. mamcx thread starter macrumors regular

    Mar 13, 2008
  4. Luke Redpath macrumors 6502a

    Nov 9, 2007
    Colchester, UK
    However, if you do use your accessor and do this in your init method:

    self.theDb = [[FMDatabase alloc] initWithPath:path];
    And then do this in your dealloc:

    [theDb release];
    Then you will have a memory leak. When you call the initWithPath method, the object returned has a retain count of 1. You then pass it into the setTheDb: method (this is the synthesized setter method used when you do self.theDb=) it sends it a retain giving it a retain count of 2. Then you release it in dealloc, bringing it back down to 1. So it leaks.

    Your original code was correct. By assigning to the instance variable directly, it only has a retain count of 1 and should be released correctly in dealloc. If you really want to use your setter, you should do this:

    _theDb = [[FMDatabase alloc] initWithPath:path];
    self.theDb = theDb;
    [_theDb release];
    But that seems a bit pointless (unless your setter does anything special).

    Out of interest, your FMDatabase initWithPath method isn't returning an autoreleased object is it? It shouldn't be.

Share This Page