NSMutableString does not listed in autoreleasepool by _CFAutoreleasePoolPrintPools()

234 views Asked by At

With ARC enabled(XCode 4.3.2, iOS 4.0), _CFAutoreleasePoolPrintPools() does not print the address of token in any pools. I checked that token is released as expected after the pool ends, so there is no issue but something goes behind scenes. I suspect that it may be something related to objc_autoreleaseReturnValue.

@autoreleasepool {
    NSMutableString *token = [NSMutableString string];
    // When following line uncommented, 
    // **token** is listed in autorelease pool by _CFAutoreleasePoolPrintPools.
    //[token appendFormat:@"%@", @"xyz"];

    NSLog(@"%@", token);

}

So, is not _CFAutoreleasePoolPrintPools() reliable? How could token be autoreleased although not listed in any autorelease pool?

Edit: As i finally find out the reason and determined that it's already been listed, the appendFormat must not work different. It seems that while calling appendFormat, memory addresses were in the ([1..F]XXX XXXX) range so _CFAutoreleasePoolPrintPools lists those addresses exactly and i could find the address when i searched.

2

There are 2 answers

0
lockedscope On BEST ANSWER

I have been bitten by left-most excessive zeroes in memory address. I was directly copying and searching the address returned for the token. NSMutableString instance actually appears as __NSCFString in the list returned by _CFAutoreleasePoolPrintPools().

(lldb) po token
(NSMutableString *) $1 = 0x[-->0<--]898e690

(lldb) po (NSString *)_CFAutoreleasePoolPrintPools()
...    
objc[731]: [0x82dc1a8]  ################  POOL 0x82dc1a8
objc[731]: [0x82dc1ac]         0x898e690  __NSCFString
1
Brian Walker On

It is the magic of objc_retainAutoreleaseReturnValue. If the autoreleased object is going to be immediately retained by the caller then it is not autoreleased - so it would not show up in the autorelease pool. I brought up the assembly assistant window and see the call to objc_retainAutoreleaseReturnValue just after the call to obj_msgSend for the [NSMutableString string] call.

See this blog post for more information. It references comments in Apple code that says:

objc_autoreleaseReturnValue() examines the caller's instructions following the return. If the caller's instructions immediately call objc_autoreleaseReturnValue, then the callee omits the -autorelease and saves the result in thread-local storage. If the caller does not look like it cooperates, then the callee calls -autorelease as usual.

objc_autoreleaseReturnValue checks if the returned value is the same as the one in thread-local storage. If it is, the value is used directly. If not, the value is assumed to be truly autoreleased and is retained again. In either case, the caller now has a retained reference to the value.

Tagged pointer objects do participate in the fast autorelease scheme, because it saves message sends. They are not entered in the autorelease pool in the slow case.