Will returning nil
under ARC in init
lead to memory leak, when [super init]
was already called, but then returned nil? Is this a legit usage?
- (id)init {
self = [super init];
if (self) {
...
return nil;
...
}
return self;
}
First of all: For Qs referring to ARC never read Apple's documentation, but clang's.
Apple's documentation simply conceals (concealed?) the execution of -init
and have wrong examples like that:
id ref = [[Class alloc] init]
You will find there a statement like " +alloc
transfers ownership". This is at least misleading, because the return value auf -init
and not the return value of +alloc
is stored.
clang's documentation is better and more precise by far. Basically they say, that +alloc
is an ownership transfer and that -init
is ownership consuming and ownership transferring.
http://clang.llvm.org/docs/AutomaticReferenceCounting.html#semantics-of-init
Methods in the init family implicitly consume their self parameter and return a retained object.
So let's have a look to the usual code:
id ref = [Class alloc];
// ref is strong: RC is +1;
id ref = [ref init];
// Three things happen her:
// 1. -init is executed
// 2. The new value is stored
// 3. The old value of ref is lost
// 1. -init is executed
// self is (silently) passed to the receiver
- (id)init
{
// Since self is strong (+1), RC is +2 now
// Since -init is ownership consuming (-1), RC is +1 now
…
return self;
// Since -init is ownership transferring (+1), RC is +2 now
}
// 2. The new value is stored
// The value comes from an ownership transfer method, so the assignment to strong ref is neutral (0), RC is still +2
// 3. The old value is lost (-1), RC is +1
The result is that the object has an RC of +1 and you have one strong reference to it in that code area. Everything is fine. (Of course there is a high potential for optimization, because in most cases neither self
nor ref
is changed, but let's keep on the regular track.)
Let's change self
inside -init
:
id ref = [Class alloc]; // Ownership transfer. RC is +1;
id ref = [ref init];
// Three things happen her:
// 1. -init is executed
// 2. The new value is stored
// 3. The old value of ref is lost
// 1. -init is executed
// self is (silently) passed to the receiver
- (id)init
{
// Since self is strong (+1), RC is +2 now
// Since -init is ownership consuming (-1), RC is +1 now
// Let's return nil as in your example
return nil;
// Because nil is returned, virtually the RC of nil is increased. self's RC == +1 is unchanged.
}
// 2. The new value is stored
// The new value is nil.
// However the value comes from an ownership transfer method, so the assignment to strong ref is neutral (0), RC is still +1
// 3. The old value is lost (your old ref and the self while executing -init) (-1), RC is 0
// The old object is dealloced, if you do not have another ref to it. Nothing leaks.
我只是在乐器中检查过-没有内存泄漏
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.