I was playing around with memory (de)allocation stuff on a simple command line app for Mac OSX 10.7 built using Xcode Version 4.2.1 with ARC enabled, and the default build setti
If you disassemble A.R.C.-produced code, every access to a weak variable is wrapped in a call to this function:
id objc_loadWeak(id *location)
{
return objc_autorelease(objc_loadWeakRetained(location));
}
This checks if the object has already been dealloced, and if not, retains and autoreleases it, for extra safety against premature deallocs.
Therefore in your third example, the early calls to method on weakRef are causing its retain count to be increased, so nilling your pointers doesn't cause it to be dealloced.
This does seem strange. You're right (in your comments) about the 2nd bit of code just being because the memory hasn't been re-used yet. But the 3rd bit of code is stranger. Here is a more simplified test case which shows this strange problem:
#import <Foundation/Foundation.h>
@interface SomeClass : NSObject
@end
@implementation SomeClass
- (void)foo {
}
@end
int main (int argc, const char * argv[]) {
@autoreleasepool {
SomeClass *objPtr1 = [[SomeClass alloc] init];
__weak SomeClass *weakRef = objPtr1;
// [weakRef foo];
[weakRef foo];
objPtr1 = nil;
NSLog(@"%p", weakRef);
return 0;
}
}
With that line commented out the output is:
$ clang -fobjc-arc -framework Foundation test.m -o test -O3 && ./test
2012-02-12 00:39:42.769 test[6684:707] 0x0
With that line uncommented out the output is:
$ clang -fobjc-arc -framework Foundation test.m -o test -O3 && ./test
2012-02-12 00:42:04.346 test[6688:707] 0x100f13f50
This seems deeply odd and looks entirely like a bug to me. I don't actually know what the answer is but thought I'd post this as an answer to get the ball rolling on figuring out what's going on.
Update:
If you build this at O0
then it seems that weakRef
is zeroed only if there are no calls to foo
. A single call to foo
will mean that it won't get zeroed.