Why __weak variable not registered in autorelease pool?

200 Views Asked by At
id obj = [[NSObject alloc] init];
@autoreleasepool{
    id __weak weakObj = obj;
    _objc_autoreleasePoolPrint();
    NSLog(@"%@",[weakObj class]);
    _objc_autoreleasePoolPrint();
}

After running the code above, I get unexpected results when printing the pool:

objc[22671]: [0x7ff544817858]  ################  POOL 0x7ff544817858
objc[22671]: ##############

I can't find the object registered in autoreleasepool. Why?

3

There are 3 best solutions below

0
Itai Ferber On

obj is never autoreleased, so it isn't placed in an autorelease pool. If you'd like obj to be autoreleased, you must call -autorelease on it, e.g.

@autoreleasepool {
    id obj = [[[NSObject alloc] init] autorelease];
    // ...
}

Note that -autorelease isn't available in ARC code.

0
Rob Napier On

I think you've misunderstood what the autorelease pool is. It's a collection of objects that will receive a release messages to when the pool drains (most commonly at the end of an event loop). It's not a list of objects that will be "automatically released by some means." It's specifically the objects that will be sent a release message by this autorelease pool (and there may be multiple pools at any given time).

It has nothing at all to do with weak. "weak" is an attribute of a variable (pointer). "autoreleased" is something that has happened to an object. Objects may be autoreleased multiple times (and this is normal).

In manual memory management, this was done very commonly by sending -autorelease to the object. That means "don't release it now; I still need it, but when the current autorelease pool drains, release it." Note that this doesn't mean "destroy it." It just means "reduce the retain count by one." This is how you say "I only care about this object until the end of the event loop" (which is a very, very common thing to want to say).

In ARC you can't directly call -autorelease, but ARC still uses the autorelease pool in some cases. A very common way is by calling objc_autoreleaseReturnValue() on something before returning it. (This isn't something you call directly. It's something ARC injects automatically when needed.) In some cases, objc_autoreleaseReturnValue() still may not actually put the object on the autorelease pool. The compiler is smart enough to detect many cases where it can avoid the pool and improve performance. There are other cases where ARC may inject autorelease, and those cases also have optimizations where it may bypass the pool.

Note that there is generally no situation where this is something your app should rely on. _objc_autoreleasePoolPrint() is an Apple-internal function, and exists for low-level debugging. Whether something is in the autorelease pool or not is highly dependent on ARC implementation details and current compiler optimizations.

0
wind On

I get the answer from this link .

The new implmenetation of __weak of Apple LLVM version 8.0.0 (clang-800.0.42.1) do not postpond the release to autoreleasepool, but use objc_release directly.