I have a doubt regarding weak
property in ARC (auto reference counting)
My understanding (correct me if I am wrong):
weak
property behaves similar to the assign
property except that when the instance that the property was pointing to gets destroyed, the ivar is made to point to nil.
Question:
weak
property retains and autoreleases. Isn't it suppose to behave like getter of the assign
property where the getter doesn't retain and autorelease ?(pls refer to the program)Program:
I have given below the program with the actual output and my expected output.
Note - When I change property from weak
to assign
my expected output is met
#import<Foundation/Foundation.h>
@interface A : NSObject
- (void) dealloc;
@end
@implementation A
- (void) dealloc
{
printf("\tinstance of A deallocated = %p\n", self);
}
@end
@interface B : NSObject
@property (weak) A* xa1;
- (void) dealloc;
@end
@implementation B
@synthesize xa1;
- (void) dealloc
{
printf("\tinstance of B deallocated = %p\n", self);
}
@end
int main()
{
B* b1 = [[B alloc] init];
@autoreleasepool //autoreleasepool 1
{
{ //block 1
A* a1 = [[A alloc] init];
printf("\ta1 = %p\n", a1);
b1.xa1 = a1;
A* a3 = b1.xa1;
printf("--- end of block 1\n");
} //at this point i expected instance pointed by a1 to be destroyed
printf("--- end of autoreleasepool 1\n");
}
printf("---- end of main\n");
return(0);
}
Actual Output:
a1 = 0x10d713f50
--- end of block 1
--- end of autoreleasepool 1
instance of A deallocated = 0x10d713f50
---- end of main
instance of B deallocated = 0x10d713d30
My Expected Output:
a1 = 0x10d713f50
--- end of block 1
instance of A deallocated = 0x10d713f50
--- end of autoreleasepool 1
---- end of main
instance of B deallocated = 0x10d713d30
Thanks
Supplying weak
on a property assumes __weak
ownership for the ivar, i.e. it's just an instruction for @synthesize
.
According to http://clang.llvm.org/docs/AutomaticReferenceCounting.html §4.2, reading __weak
variable requires retaining the object (and releasing after, of course):
Reading occurs when performing a lvalue-to-rvalue conversion on an object lvalue.
- For __weak objects, the current pointee is retained and then released at the end of the current full-expression. This must execute atomically with respect to assignments and to the final release of the pointee.
- For all other objects, the lvalue is loaded with primitive semantics.
It does not say why, but think of what happens if the object you got from __weak variable dies before you even started using it. The purpose of weak pointer is to make sure you have either nil
or a valid object with well-known lifetime, that is why reading its value implies retaining the pointee (and then property's getter returns it autoreleased).
This is not unique to Obj-C, it's common idiom to all weak pointer implementations (both refcounted and garbage collected). Weak pointers can not give out pointer value directly, they have to create strong pointer to 'hold' object to make sure it won't die before caller has even started using it. In Obj-C, it's retain-autorelease; in C++, weak_ptr creates shared_ptr first, in garbage-collected environments, a strong reference is returned and the object's lifetime is prolonged silently.