Objective-C - weak object is registered in autoreleasepool automatically?

自闭症网瘾萝莉.ら 提交于 2019-12-23 17:22:33

问题


I am reading Pro Multithreading and Memory Management for iOS and OS X with ARC, Grand Central Dispatch, and Blocks written by Kazuki Sakamoto.

The book wrote:

When a variable with a __weak qualifier is used, the object is always registered in autoreleasepool.

id __weak obj1 = obj0;
NSLog(@"class=%@", [obj1 class]);

The above source code is equivalent to:

id __weak obj1 = obj0;
id __autoreleasing tmp = obj1;
NSLog(@"class=%@", [tmp class]);

Why does the object need to be registered in autoreleasepool in order to use the object via the __weak qualified variable? Because a variable, which is qualified with __weak, does not have a strong reference, the object might be disposed of at any point. If the object is registered in autoreleasepool, until @autoreleasepool block is left, the object must exist. So, to use the objects via __weak variable safely, the object is registered in autoreleasepool automatically.

I have given below the program to verify what the author wrote.

@interface A : NSObject
- (void) dealloc;
@end

@implementation A
- (void) dealloc
{
    NSLog(@"dealloc");
}
@end


int main()
{
    @autoreleasepool
    {
        {
            A *obj0 = [[A alloc] init];
            id __weak obj1 = obj0;
            NSLog(@"end of block");
        }
        NSLog(@"end of autoreleasepool");
    }

    return(0);
}

Actual Output:

end of block
dealloc
end of autoreleasepool

Expected Output:

end of block
end of autoreleasepool
dealloc

obj1 is disposed at the end of the block. It's obvious that obj1 isn't registered in autoreleasepool automatically.

If I manually add

id __autoreleasing tmp = obj1;

The output is expected. obj1 is disposed at the end of the autoreleasepool.

Could anyone tell me what's going on? Is the weak object registered in autoreleasepool automatically?

Thanks!


回答1:


When a variable with a __weak qualifier is used, the object is always registered in autoreleasepool.

That is absolute and total nonsense. __weak has nothing to do with autorelease pools whatsoever.

What the compiler does is add the location of the pointer to the list of "weak pointer" locations - note the location of the pointer, not the object. So when the object itself is released, all weak variables pointing to it can be set to nil.

And of course the compiler is clever and will optimise that kind of thing away when it can prove that it is not necessary.

What the author says about using weak variables safely is nonsense. The whole point of a weak variable is that it doesn't keep the object alive. So preventing the object from going away would be absolute nonsense. The whole idea is that it can go away, so sometimes you will check if the object is still there.

I don't have the book, so I cannot know if you are quoting the book correctly. If you are quoting it correctly, then the book is spouting dangerous nonsense and should be avoided. Well, to be honest, "Pro Multithreading" in a book title is off-putting already.

Could anyone tell me what's going on? Is the weak object registered in autoreleasepool automatically?

Absolutely, definitely not. That would be absolutely stupid.




回答2:


It appears that ARC at the end of each scope decides whether or not to release + dealloc local variables.

from an article i found on the matter

ARC variables are released as soon as the optimizer decides that they are no longer referenced, so the compiler is free to release uicolor after fetching the CGColor. Current compiler implementations do seem to wait until the end of scope, but that’s not guaranteed. The LLVM Project’s ARC notes say: “By default, local variables of automatic storage duration do not have precise lifetime semantics.”

so its seems at the end of the inner scope to your @autoreleasepool, arc is releasing the local variable




回答3:


I am reading the same book now and I found this part very confusing too. And I wrote a very similar program to test it and it didn't work. After some googling I've found that weak pointer is added to autorelease pool indeed:

Precondition: object is a valid pointer which either contains a null pointer or has been registered as a __weak object.

If object is registered as a __weak object, and the last value stored into object has not yet been deallocated or begun deallocation, retains and autoreleases that value and returns it. Otherwise returns null. Equivalent to the following code:

id objc_loadWeak(id *object) {   
    return objc_autorelease(objc_loadWeakRetained(object)); 
} 

Must be atomic with respect to calls to objc_storeWeak on object.

Rationale: Loading weak references would be inherently prone to race conditions without the retain.

But I still can't understand why object is released instantly, not when autorelease pool is drained. My guess some serious magic like compiler optimizations is involved.



来源:https://stackoverflow.com/questions/34083137/objective-c-weak-object-is-registered-in-autoreleasepool-automatically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!