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

Discussion in 'iPhone/iPad Programming' started by mamcx, Jan 8, 2009.

  1. 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. 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. thread starter macrumors regular

    Joined:
    Mar 13, 2008
    #3
    Thank you, that do the trick ;)
     
  4. macrumors 6502a

    Joined:
    Nov 9, 2007
    #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