How is release handled for @synthesized retain properties?
Solution 1:
Q1:
No. @synthesize
does not modify the -dealloc
for you. You have to -release
the name
yourself.
Q2:
Yes it will leak. Same reason as Q1.
Q3:
No it won't double-release. Same reason as Q1.
Q4:
Yes it will leak. Same reason as Q1.
Q5:
No it won't double-release. Same reason as Q1.
You can check this yourself by overriding -retain
and -release
and -dealloc
to report what is going on.
#import <Foundation/Foundation.h>
@interface X : NSObject {}
@end
@implementation X
-(oneway void)release {
NSLog(@"Releasing %p, next count = %d", self, [self retainCount]-1);
[super release];
}
-(id)retain {
NSLog(@"Retaining %p, next count = %d", self, [self retainCount]+1);
return [super retain];
}
-(void)dealloc {
NSLog(@"Dealloc %p", self);
[super dealloc];
}
@end
@interface Y : NSObject {
X* x;
}
@property (nonatomic, retain) X* x;
@end
@implementation Y
@synthesize x;
- (void)dealloc { [x release]; [super dealloc]; }
@end
int main () {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
Y* y = [[Y alloc] init];
X* x = [[X alloc] init];
y.x = x;
[y release];
[x release];
[pool drain];
return 0;
}
In Q1, Q2 and Q4, the last -retainCount
of x
is 1, so there is a leak, and in Q3 and Q5 the last -retainCount
is 0 and -dealloc
is called, so there is no leak.
Solution 2:
From the Objective-C documentation on properties:
dealloc
Declared properties fundamentally take the place of accessor method declarations; when you synthesize a property, the compiler only creates any absent accessor methods. There is no direct interaction with the dealloc method—properties are not automatically released for you. Declared properties do, however, provide a useful way to cross-check the implementation of your dealloc method: you can look for all the property declarations in your header file and make sure that object properties not marked assign are released, and those marked assign are not released.
This essentially answers all your questions.
Solution 3:
The simple and general rule: if you allocate, retain, or copy an object, YOU have to release it.
When you use the retain
setter semantic setting in a @synthesize
statement, you're asking the compiler to build for you a setter that calls retain
on the object. Nothing more, nothing less. And since you are retaining that object (even though it's via magically auto-generated code), you have to release it, and where to release it is in -(void)dealloc
.
Solution 4:
Something else it's worth knowing - if you have a synthesised property, setting that property to nil (using dot syntax, of course) will release the ivar for you.