1
votes

I have a doubt regarding autoreleasepool in an Auto Reference Counting (ARC)

In my example (pasted below) I have an autoreleasepool and I have no statements within the autoreleasepool block. There is an autoreleased instance (a3) after the autoreleasepool block.

Expected Behavior:

I expected the following statement to cause a memory leak because it is not encapsulated with in an autoreleasepool.

A* a3 = b1.xa1;

Actual Behavior:

Actual behavior is that no memory leak error is thrown at runtime

Note:

If the autoreleasepool is moved after the initialization of a3, then at runtime there is a memory leak error thrown

My Understanding:

Only statements with in an autoreleasepool will have the effect of an autorelease pool, but that doesn't seem to be the case as per my example.

Question:

  1. What is the reason why this happens ?
  2. Is there any significance of enclosing statements with an autoreleasepool block? or is it just good enough to have an empty autoreleasepool block before the autoreleased instance ? If so why ?

Summary of my question

The question is more about enclosing statements within the autoreleasepool seem to have the same effect as the placing statements after the autoreleasepool even it is outside the autoreleasepool

Code:

#import<Foundation/Foundation.h>

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

@implementation A
- (void) dealloc { printf("instance of A deallocated = %p\n", self); };
@end

@interface B : NSObject
@property (weak) A* xa1;
- (void) dealloc;
@end

@implementation B
@synthesize xa1;
- (void) dealloc { printf("instance of B deallocated = %p\n", self); };
@end

int main()
{
    system("clear");

    B* b1 = [[B alloc] init];
    A* a1 = [[A alloc] init];
    A* a2 = [[A alloc] init];

    b1.xa1 = a1; 

    @autoreleasepool
    {}  

    A* a3 = b1.xa1;                     //I expected this to throw a memory leak error, but it doesn't
                                        //Note - b1.xa1 returns an autoreleased instance

    printf("--- end of main\n");

    return(0);
}
1
What is a "memory leak error"? What's the text that you see, and in what context?jscs
The memory leak error is pasted below (when the autoreleasepool a3 initialization is moved before the autoreleasepool): objc[2668]: Object 0x105313b90 of class A autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debuguser1046037

1 Answers

2
votes
  1. What is the reason why this happens?

While I think technically the A* a3 = b1.xa1; line is "wrong", ARC is smart enough to correctly dispose of the returned object without actually using an autorelease pool. This is a performance optimization of ARC (the use of the autorelease pool is not free). Basically, ARC is injecting [a1 relea From Apple's Transitioning to ARC Release Notes

The compiler efficiently eliminates many extraneous retain/release calls and much effort has been invested in speeding up the Objective-C runtime in general. In particular, the common “return a retain/autoreleased object” pattern is much faster and does not actually put the object into the autorelease pool, when the caller of the method is ARC code.


  1. Is there any significance of enclosing statements with an autoreleasepool? or is it just good enough to have an empty autoreleasepool block before the autoreleased instance? If so why?

Yes. While this specific case happens to indicate otherwise, in general, autorelease pools are meaningful. Everything in this document on Autorelease Pools is still valid: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html