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

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

  1. mamcx
    Expand Collapse
    macrumors regular

    Joined:
    Mar 13, 2008
    #1
    Hi, I have this:

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

    Code:
    - (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
    Expand Collapse
    Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #2
    Have you synthesized the property accessors? Where do you use them? You should be using something like

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

    Joined:
    Mar 13, 2008
  4. Luke Redpath
    Expand Collapse
    macrumors 6502a

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

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

    Code:
    [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:

    Code:
    _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