When ARC enabled, following code causes the obj retained twice for the block by calling objc_retain() and objc_retainBlock().(So retainCount becomes 3 after the block definition.)
I checked that obj is not in autorelease pool and there are two objc_release() calls for obj at the end of the method. (I know counting retains does not make sense but i am checking the objc_retain() calls, not barely checking retain counts.)
What is the rationale behind this?
-(void)myMethod
{
NSObject *obj = [[NSObject alloc] init];
NSLog(#"obj %# retaincount %ld", obj, CFGetRetainCount((__bridge CFTypeRef)obj));
void (^myBlock)(void) = ^()
{
NSLog(#"obj %# retaincount %ld", obj, CFGetRetainCount((__bridge CFTypeRef)obj));
};
NSLog(#"obj %# retaincount %ld", obj, CFGetRetainCount((__bridge CFTypeRef)obj));
myBlock();
}
Isn't it enough to retain the obj just once for capturing it by the block?
Note: Also, when i remove the myBlock variable and the call for it, so just with ^() {...} definition and that definition could never be called, obj is still retained with objc_retain() which seems weird. I am using XCode 4.3.2.
www.whentouseretaincount.com -- i.e. don't use retainCount as it'll cause nothing but confusion. Even for learning the innards.
If you want to know how and when blocks retain objects, you should look at the compiler, runtime, and blocks runtime sources. All are available.
A block may or may not retain an object. Specifically, a block may only retain an object when the block is copied (as long as the object reference isn't __weak).
Similarly, but orthogonally, ARC's retain/release behavior changes based on the optimization level of the compiler. In particular, DEBUG (-O0) code tends to have lots of retain/release. -Os (optimized) code will have many of these optimized out.
Please read this: http://whentouseretaincount.com/
You shouldn't use retain count, the apple developers who wrote it advise against it, a lot of smart people advise against it and i'm telling you not to use it.
As for retain cycles its good practice to have a weak property outside of your block scope as such:
__weak typeof(obj) weakObj = obj;
void (^block)(void) = ^{
[weakObj method];
};
Related
As we know, using strong self within a block can lead to retain cycles and memory leak. Is the common practice to use weak self in a block, or is it better to assign the weak self to strong within the block and then use it as such so the weak self is not released during block execution? Does it matter since weak self will be zero-ed out anyway?
Due to the volatile nature of weak variables, you should use them with care. If you are using weak variables in a multithreading environment, it is considered good practice to assign the weak variable to a strong one and check for nil before using. This will ensure that the object will not be released in the middle of your method, causing unexpected results.
Consider the following case:
__weak id var;
//...
if(var != nil)
{
//var was released here on another thread and there are not more retaining references.
[anotherObj performActionWithAnObjThatMustNotBeNil:var]; //<- You may crash here.
}
The compiler can be configured to throw a warning on a consecutive access of a weak variable.
On the other hand, if your use is in the main thread, and all calls to the object are on the main thread, this problem is moot, since the object will either be released before the block call or after, thus it being safe to access the weak variable directly.
There are two possible questions here that are easy to get confused:
Is it possible for a __weak reference to become nil in the middle of a method?
id __strong strongObject = ...;
id __weak weakObject = strongObject;
dispatch_async(dispatch_get_main_queue(), ^{
[weakObject method1]; // if weakObject is non-nil here
[weakObject method2]; // can it become non-nil here?
});
Yes! Xcode will even warn you about it.
Is it possible for self to become nil in the middle of a method if the method is called on a __weak lvalue as below?
id __strong strongObject = ...;
id __weak weakObject = strongObject;
dispatch_async(dispatch_get_main_queue(), ^{
// is it possible for weakObject to be deallocated
// while methodUsingSelf is being called?
[weakObject methodUsingSelf];
});
- (void)methodUsingSelf {
NSLog(#"%#", self); // Could this be non-nil
NSLog(#"%#", self); // while this is nil?
}
No! Joe Groff, of the Swift team at Apple, said so:
self is guaranteed kept alive by ObjC ARC while a method on self is
executing.
Clang's official ARC documentation covers this case in the Semantics/Reading subsection:
Reading occurs when performing a lvalue-to-rvalue conversion on an
object lvalue.
For __weak objects, the current pointee is retained and then released
at the end of the current full-expression. This must execute
atomically with respect to assignments and to the final release of the
pointee.
Thus, calling a method on a __weak variable, is roughly equivalent to the following Manual Retain/Release (MRR) code:
id retainedObject = ...;
id assignedObject = strongObject;
dispatch_async(dispatch_get_main_queue(), ^{
{
[assignedObject retain];
[assignedObject methodUsingSelf];
[assignedObject release];
}
});
Of course, in MRR, [assignedObject retain]; might crash because the object assignedObject points to might have been deallocated, so assignedObject might point to garbage. ARC doesn't have this problem because it zeroes weak references.
I think that even if using the weak will work and be retained as long as needed, assigning it to strong before using will make it more readable and "worries free"...:
__weak id weakThing = thing;
thing.someBlock = ^{
if (weakThing) {
id strongThing = weakThing;
strongThing doThisWithThat...
}
};
Compiler won't complain and it is safe and maybe not less importantly - easy to understand for John Doe who will try to read this code tomorrow....
You can continue to use the weak self. The only time you'd need to use strong self is if you are trying to access a self->ivar directly, instead of going through a property.
Im doing some research on blocks,
the code here
typedef NSString* (^MyBlock)(void);
#property(copy,nonatomic) MyBlock block1;
in viewdidload
self.block1 = ^{
self
NSLog(#"do block");
return #"a";
};
of course the self is retained, then I do a
self.block = nil;
by checking the retain count of self, I found it reduced by 1, no retain cycle.
I believe this is the correct situation, the block retains self, when release the block, self gets released. retaincount reduced.
I made a litte change, and things coms strange:
make block a local variable.
in viewdidload
MyBlock block1 = ^{
self
NSLog(#"do block");
return #"a";
};
[block copy]; // retain count of self gets added.
[block release]; // retain count of sell still the same
why? I tried Block_release(), its the same. and when putting a local variable like NSArray in the block, the retain count fellows the same rule as self.
there must be some thing different inside of #property, anyone researched this before?
pls help.
Additionally, I do this in ARC, a local variable block will made the retain cycle, and a instance variable didnt, due to the autorelease, it holds the self, and few seconds later, it released and self object get released normally.
is it because the instance variable and local variable are alloc on different parts in memory? stack ? heap?, are they both copied to heap when do a [block copy]?
EDIT :
not instance variable and local variable. using #property makes it different, any explanations?
The problem is that using retainCount to figure out things like this is futile. The retainCount will not reflect autorelease state and the compiler -- the ARC compiler, in particular -- may generate different code (in particular, the optimizer has a tendency to eliminate unnecessary retain/autorelease pairs).
Use the Allocations Instrument and turn on reference event tracking. Then you can look at each retain/release event on the object, the exact stack trace where it happened, and know exactly what is going on.
Under non-ARC, when you assign to an iVar, nothing happens. When you go through the setter, a retain setter will cause the object to be retaind. Under ARC, a block will be copied to the heap automatically in a number of cases, triggering a retain of the captured object when the block is copied.
http://www.whentouseretaincount.com/
MyBlock getBlocks()
{
MyBlock myBlock = ^{
NSLog(#"Hello World!");
};
return myBlock;
}
int main(int argc, const char * argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
MyBlock myBlock = getBlocks();
myBlock();
[pool drain];
return 0;
}
Why does this snippet of code work? myBlock should be destroyed.
By the way, this snippet also works:
NSObject *obj = [[NSObject alloc] init];
NSLog(#"%ld", [obj retainCount]);
MyBlock myBlock = ^{
NSLog(#"Hello World!");
NSLog(#"%ld", [obj retainCount]);
};
[obj release];
but [obj retainCount] in block prints 1 instead 2, why?
Blocks can be allocated on the stack for performance reasons and only migrate away to the heap when you copy them. If your block doesn't capture any values, the compiler can also turn it into a global block whose memory exists in some fixed static memory location.
Since your getBlocks block doesn't capture anything, it is a global block and its memory can't be disposed. It doesn't have reference counting semantics and retain/release won't do anything. Its reference will always be valid and you'll always be able to call it.
If the block in getBlocks did capture some values, it would be a local stack-allocated block, and the method would be returning a reference to that stack memory, which is of course very dangerous. The code may even still work in this case and you'd be able to call it even though it is sitting in unowned stack memory (as long as that memory hasn't been trashed by somebody else by the time you call the block).
I believe your second example is also demonstrating the side effects of a stack-allocated block. The objects captured by a stack-allocated block will only be retained when the block is actually copied to the heap for the first time. This doesn't happen in your code so obj isn't retained by the block.
This does mean that after calling [obj release] in your example, the block is now capturing a dangling pointer. Using ARC will fix all these messy details for you.
See How blocks are implemented (and the consequences) (Cocoa With Love) for more details.
Edit: Also, obligatory link to when to use retainCount
Why does this snippet of code work?
The first snipped is working because the block implementation has no reference to the surrounding scope, and it's therefore configured by clang as a global block. This causes the block not to be on the stack as it would normally be.
myBlock should be destroyed.
Stack frames (and their local variable) don't get destroyed. Their memory is made available for further allocation. Anyway, due to the simplicity of your example, you're getting a global block which doesn't live on the stack frame.
If you were making any reference to the surrounding scope you would have had a stack-based block and myBlock would have been a dangling pointer to an on-owned memory location, likely leading to a crash.
[obj retainCount] in block prints 1 instead 2, why?
Sounds reasonable.
You are allocating an object (retain count: 1), the block is retaining it (retain count: 2), you are releasing it (retain count: 1), the block is eventually executed (retain count still 1).
As a general note, anyway, don't rely upon retainCount when reasoning about memory. The memory management process has a lot going on under the hood, and you cannot definitely say anything only by looking at the value of retainCount, due to internal details of the implementation that you cannot possibly take into account. More on the subject here: http://whentouseretaincount.com/
I was migrating a block of code to automatic reference counting (ARC), and had the ARC migrator throw the error
NSInvocation's setArgument is not safe to be used with an object with
ownership other than __unsafe_unretained
on code where I had allocated an object using something like
NSDecimalNumber *testNumber1 = [[NSDecimalNumber alloc] initWithString:#"1.0"];
then set it as an NSInvocation argument using
[theInvocation setArgument:&testNumber1 atIndex:2];
Why is it preventing you from doing this? It seems just as bad to use __unsafe_unretained objects as arguments. For example, the following code causes a crash under ARC:
NSDecimalNumber *testNumber1 = [[NSDecimalNumber alloc] initWithString:#"1.0"];
NSMutableArray *testArray = [[NSMutableArray alloc] init];
__unsafe_unretained NSDecimalNumber *tempNumber = testNumber1;
NSLog(#"Array count before invocation: %ld", [testArray count]);
// [testArray addObject:testNumber1];
SEL theSelector = #selector(addObject:);
NSMethodSignature *sig = [testArray methodSignatureForSelector:theSelector];
NSInvocation *theInvocation = [NSInvocation invocationWithMethodSignature:sig];
[theInvocation setTarget:testArray];
[theInvocation setSelector:theSelector];
[theInvocation setArgument:&tempNumber atIndex:2];
// [theInvocation retainArguments];
// Let's say we don't use this invocation until after the original pointer is gone
testNumber1 = nil;
[theInvocation invoke];
theInvocation = nil;
NSLog(#"Array count after invocation: %ld", [testArray count]);
testArray = nil;
due to the overrelease of testNumber1, because the temporary __unsafe_unretained tempNumber variable is not holding on to it after the original pointer is set to nil (simulating a case where the invocation is used after the original reference to an argument has gone away). If the -retainArguments line is uncommented (causing the NSInvocation to hold on to the argument), this code does not crash.
The exact same crash happens if I use testNumber1 directly as an argument to -setArgument:, and it's also fixed if you use -retainArguments. Why, then, does the ARC migrator say that using a strongly held pointer as an argument to NSInvocation's -setArgument: is unsafe, unless you use something that is __unsafe_unretained?
This is a complete guess, but might it be something to do with the argument being passed in by reference as a void*?
In the case you've mentioned, this doesn't really seem a problem, but if you were to call, eg. getArgument:atIndex: then the compiler wouldn't have any way of knowing whether the returned argument needed to be retained.
From NSInvocation.h:
- (void)getArgument:(void *)argumentLocation atIndex:(NSInteger)idx;
- (void)setArgument:(void *)argumentLocation atIndex:(NSInteger)idx;
Given that the compiler doesn't know whether the method will return by reference or not (these two method declarations have identical types and attributes), perhaps the migrator is being (sensibly) cautious and telling you to avoid void pointers to strong pointers?
Eg:
NSDecimalNumber* val;
[anInvocation getArgument:&val atIndex:2];
anInvocation = nil;
NSLog(#"%#", val); // kaboom!
__unsafe_unretained NSDecimalNumber* tempVal;
[anInvocation getArgument:&tempVal atIndex:2];
NSDecimalNumber* val = tempVal;
anInvocation = nil;
NSLog(#"%#", val); // fine
An NSInvocation by default does not retain or copy given arguments for efficiency, so each object passed as argument must still live when the invocation is invoked. That means the pointers passed to -setArgument:atIndex: are handled as __unsafe_unretained.
The two lines of MRR code you posted got away with this: testNumber1 was never released. That would have lead to a memory leak, but would have worked. In ARC though, testNumber1 will be released anywhere between its last use and the end of the block in which it is defined, so it will be deallocated. By migrating to ARC, the code may crash, so the ARC migration tool prevents you from migrating:
NSInvocation's setArgument is not safe to be used with an object with
ownership other than __unsafe_unretained
Simply passing the pointer as __unsafe_unretained won't fix the problem, you have to make sure that the argument is still around when the invocation gets called. One way to do this is call -retainArguments as you did (or even better: directly after creating the NSInvocation). Then the invocation retains all its arguments, and so it keeps everything needed for being invoked around. That may be not as efficient, but it's definitely preferable to a crash ;)
Why is it preventing you from doing this? It seems just as bad to use __unsafe_unretained objects as arguments.
The error message could be improved but the migrator is not saying that __unsafe_unretained objects are safe to be used with NSInvocation (there's nothing safe with __unsafe_unretained, it is in the name). The purpose of the error is to get your attention that passing strong/weak objects to that API is not safe, your code can blow up at runtime, and you should check the code to make sure it won't.
By using __unsafe_unretained you are basically introducing explicit unsafe points in your code where you are taking control and responsibility of what happens. It is good hygiene to make these unsafe points visible in the code when dealing with NSInvocation, instead of being under the illusion that ARC will correctly handle things with that API.
Throwing in my complete guess here.
This is likely directly related to retainArguments existing at all on the invocation. In general all methods describe how they will handle any arguments sent to them with annotations directly in the parameter. That can't work in the NSInvocation case because the runtime doesn't know what the invocation will do with the parameter. ARC's purpose is to do its best to guarantee no leaks, without these annotations it is on the programmer to verify there isn't a leak. By forcing you to use __unsafe_unretained its forcing you to do this.
I would chalk this up to one of the quirks with ARC (others include some things not supporting weak references).
The important thing here is the standard behaviour of NSInvocation:
By default, arguments are not retained and C string arguments are not being copied. Therefore under ARC your code can behave as follows:
// Creating the testNumber
NSDecimalNumber *testNumber1 = [[NSDecimalNumber alloc] initWithString:#"1.0"];
// Set the number as argument
[theInvocation setArgument:&testNumber1 atIndex:2];
// At this point ARC can/will deallocate testNumber1,
// since NSInvocation does not retain the argument
// and we don't reference testNumber1 anymore
// Calling the retainArguments method happens too late.
[theInvocation retainArguments];
// This will most likely result in a bad access since the invocation references an invalid pointer or nil
[theInvocation invoke];
Therefore the migrator tells you:
At this point you have to explicitly ensure that your object is being retained long enough. Therefore create an unsafe_unretained variable (where you have to keep in mind that ARC won't manage it for you).
According to Apple Doc NSInvocation:
This class does not retain the arguments for the contained invocation by default. If those objects might disappear between the time you create your instance of NSInvocation and the time you use it, you should explicitly retain the objects yourself or invoke the retainArguments method to have the invocation object retain them itself.
I am trying to get the hang of retain / release. I get that they are a matched set. But I don't know when I have to retain references.
-(void)sampleMethod:(RandomClass *) obj {
[obj retain];
// Do stuff to object...
[obj release];
}
Is it necessary to retain (and thus release) obj?
I am worried about obj going away. Does it follow that you must (if) retain reference parameters as soon as possible in the function? What about the space of time between the functions call and the first instruction of the function?
Thanks!
Short answer; use ARC.
Joe's answer is more or less correct. Until it isn't.
In general, there is no need to retain arguments or return values from other methods. However, the resulting code only works by coincidence and convention, not by algorithmic analysis.
Consider:
NSString *foo = [aMutableArray objectAtIndex: 5];
[aMutableArray removeObjectAtindex: 5];
[someTextField setTextValue: foo];
BOOM!
Your code just crashed. Maybe (it won't crash if foo happens to be a constant string or happens to have been retained by something else or happens to have been retain/autoreleased somewhere else).
Technically, that should be:
NSString *foo = [aMutableArray objectAtIndex: 5];
[foo retain];
[aMutableArray removeObjectAtindex: 5];
[someTextField setTextValue: foo];
[foo release];
That is, foo should be retained the moment it comes into scope and released the moment it is no longer used in a scope. Or you could [[foo retain] autorelease];, but autorelease pressure can be a problem (it generally isn't, but it can be).
ARC does this kind of analysis and would ensure that foo is retained as shown above when necessary.
You do not have to worry about the object being passed going away so there is no need to retain it. Proper memory management* ensures that the object will live for the duration of your method because it will be within the same thread as the caller, therefore the autorelease pool for that thread should not be drained and the caller can not release the object until your method has returned. This even holds true with methods such as performSelectorInBackground because that will retain the argument.
*Proper memory management - This means each thread that uses auto released objects gets it own autorelease pool that is drained within the same context it is created and objects passed across threads are properly retained.