ARC and __unsafe_unretained - objective-c

I think I have a pretty good understanding of ARC and the proper use cases for selecting an appropriate lifetime qualifiers (__strong, __weak, __unsafe_unretained, and __autoreleasing). However, in my testing, I've found one example that doesn't make sense to me.
As I understand it, both __weak and __unsafe_unretained do not add a retain count. Therefore, if there are no other __strong pointers to the object, it is instantly deallocated (with immutable strings being an exception to this rule). The only difference in this process is that __weak pointers are set to nil, and __unsafe_unretained pointers are left alone.
If I create a __weak pointer to a simple, custom object (composed of one NSString property), I see the expected (null) value when trying to access a property:
Test * __weak myTest = [[Test alloc] init];
myTest.myVal = #"Hi!";
NSLog(#"Value: %#", myTest.myVal); // Prints Value: (null)
Similarly, I would expect the __unsafe_unretained lifetime qualifier to cause a crash, due to the resulting dangling pointer. However, it doesn't. In this next test, I see the actual value:
Test * __unsafe_unretained myTest = [[Test alloc] init];
myTest.myVal = #"Hi!";
NSLog(#"Value: %#", myTest.myVal); // Prints Value: Hi!
Why doesn't the __unsafe_unretained object become deallocated?
[EDIT]: The object is being deallocated... if I try to substitute lines 2 - 3 with NSLog(#"%#", myTest); the app crashes (and an overridden dealloc in Test is being called immediately after the first line). I know that immutable strings will continue to be available even with __unsafe_unretained, and that a direct pointer to the NSString would work. I am just surprised that I could set a property on a deallocated object (line 2), and that it could later be dereferenced from a pointer to the deallocated object it belonged to (line 3)! If anyone could explain that, it would definitely answer my question.

I am just surprised that I could set a property on a deallocated object (line 2), and that it could later be dereferenced from a pointer to the deallocated object it belonged to (line 3)! If anyone could explain that, it would definitely answer my question.
When the object is deallocated it is not zeroed. As you have a pointer to the deallocated object and the property value is stored at some offset to that pointer it is possible that storing and retrieving that property value will succeed after deallocation, it is also quite possible that everything will blow up for some reason or other.
That your code works is quite fragile, try debugging it with "Show Disassembly While Debugging" and stepping through, you'll probably hit an access violation, or take down Xcode itself...
You should never be surprised that strange things happen in C, Objective-C, C++ or any of the family; instead reserve your surprise for so few strange things happening!

Because the constant string in objc is a constant pointer to a heap address and the address is still valid.
edited after comment:
Maybe because the memory at the test objects address hasn't been overwritten and still contains that object? Speculating....

You can see when Test is deallocated by implementing its -dealloc method and adding some simple logging.
However, even if Test is deallocated immediately, the memory it occupied in RAM may remain unchanged at the time you call myVal.

#"hi!" produces a static global constant string instance that is, effectively, a singleton. Thus, it'll never be deallocated because it wasn't really allocated in the first place (at least, it really isn't a normal heap allocation).
Anytime you want to explore object lifespan issues, always use a subclass of NSObject both to guarantee behavior and to make it easy to drop in logging hooks by overriding behavior.

Nothing strange there…
You need to have at least 1 strong reference to object to keep it alive.
Test * anTest = [[Test alloc] init];
Test * __weak myTest = anTest;
myTest.myVal = #"Hi!";
NSLog(#"Value: %#", myTest.myVal); // Prints Value: (Hi)

Related

retain release common practice in iOS setter methods

The common practice in IOS setters is the following:
- (void)setMyString:(NSString *)newString {
if ( newString != myString ) {
[myString release];
myString = [newString retain];
}
}
On the contrary this is not good practice
- (void)setMyString:(NSString *)newString {
if ( myString != nil ) [myString release];
myString = [newString retain];
}
}
What is the reason checking for equality in the first case? What is the problem in the seconds case?
If you set something like this [object setMyString:[object myString]]; without checking for equality - it will be crash! Because it will be released before you send it message retain. (in case when only object own string). Also in first example we checking for equality to avoid extra operations.
I know this is somewhat redundant, but...
If the new and old object are the same then you send release to the old object and it gets deallocated, the pointer to the new object will become a dangling pointer as the object it pointed to will no longer exist (since it pointed to the same object as the old object pointer). Ex. if myString and newString point to the same instance who has a retain count of one, then you subtract one, it'll equal zero. it's too late to add one now, because it'll get deallocated. However, reverse the calls to retain and release and it should be fine. If the retain count is one and you add one, it's now two, and you can safely send release. In general, I'd say before you disown an object, assert ownership of the new one first.
Also, the first type of setter would be what you would use for retain/strong style setter. If it were assign you wouldn't need to retain/release as no ownership is supposed to be asserted. NSStrings often have a copy style setter which copies the argument and uses that, which would create a copy instead of retaining. I would generally use copy for anything with a mutable subclass as you wouldn't want someone passing in a NSMutableString and mutating it behind your back. This page goes into accessors, and you'll notice that they retain the new value before releasing the old one, and explain why.
You may take this to though the memory management, https://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/.

How to cast from id __autoreleasing * to void ** in ARC?

I'm trying to cast from an id __autoreleasing * to a CFTypeRef * (void **).
I've tried:
id __autoreleasing *arg = [OCMArg setTo:mockData];
CFTypeRef expectedResult = (__bridge CFTypeRef) *arg;
[[[self.mockSecItemService expect] andReturnValue:OCMOCK_VALUE(mockCopyStatus)] copyItemMatching:queryCheck
result:&expectedResult];
But the code crashes when the autorelease pool is drained.
How does one convert to void** in an ARC environment?
I do not know the APIs you are using, so I'm not 100% sure of what's going on. I googled and they seem to be part of OCMock. I downloaded it and (without installing it as I'm not interested) I rapidly browsed the source.
I see something very fishy in that code. Here's how they implement the first method you call:
#implementation OCMArg
....
+ (id *)setTo:(id)value
{
return (id *)[[[OCMPassByRefSetter alloc] initWithValue:value] autorelease];
}
So they are returning an id* which is really just an id.
To me that's either a nonsense/error or an attempt to manipulate ObjC internals (even if undocumented, the first thing an ObjC object stores is in fact a pointer to the object class and is therefore of type Class which is compatible with id, therefore it somehow is valid to cast a pointer to an object or an id that refers to an object, to Class* or id*). I have no time or interest in going and studying the whole API to figure out why they do that. They may actually have a good reason (for example if you only pass that result to another API that knows what it's supposed to be, but you are doing more than that here). Instead of studying OCMock I'll try to explain you what is happening as far as I can say (ObjC and ARC).
id __autoreleasing *arg = [OCMArg setTo:mockData];
ARC will do absolutely nothing in this line of code.
What that method does you can see above. Class OCMPassByRefSetter is a simple class that just stores the argument after retaining it, so mockData is retained. The OCMPassByRefSetter is autoreleased and will disappear at the next drain (releasing the mockData and making *arg reference to released memory).
Note that arg in fact points to the isa of the OCMPassByRefSetter (the isa is the "first" ivar of any object, it's of type Class and points to the class of the object. But this is undocumented and may change at any time).
CFTypeRef expectedResult = (__bridge CFTypeRef) *arg;
*arg is of type id which is compatible with CFTypeRef, so the cast is valid. You use __bridge so ARC does absolutely nothing.
If arg pointed to a "toll free bridged" CF/Cocoa class this would be perfectly valid code but you'd have to be careful that expectedResult would become invalid at the next drain (it's not retained, but it's live as an autoreleased instance).
[[[self.mockSecItemService expect] andReturnValue:OCMOCK_VALUE(mockCopyStatus)] copyItemMatching:queryCheck
result:&expectedResult];
No idea what this line does. Given the prototype you posted in the comment above, ARC does nothing on the part result:&expectedResult.
You say it's a wrapper around SecItemCopyMatching, but as I understand it it's more than that. If it was just immediately calling SecItemCopyMatching passing it the result: argument, you'd likely be messing things up. But the name expectedResult and the fact that this is OCMock makes me think this is a little more complex than that.
You'll have to investigate it yourself a bit. But remember:
as soon as the current function exits, the argument you passed (&expectedResult) will become invalid as it's a local variable.
as soon as there is a drain, the value of expectedResult will become invalid, as that address points to memory that is going to be deallocated by the drain.
doing anything with the value of expectedResult is likely do be going very wrong as I do not think that a Class qualifies as "toll free bridged".
I suspect, but I may be very wrong, that you are not using the OCMock apis the way they are intended to be used. But on this front I cannot help you, and maybe you are actually doing it right.
Rather than try and figure out how to cast the variable into the correct format (OCMock is doing some complex things internally), I added another method, to handle the conversion.
- (OSStatus)findItemMatching:(NSDictionary *)query result:(id __autoreleasing *)outResult {
NSAssert(outResult, #"outResult is required");
CFTypeRef result = nil;
OSStatus status = [self copyItemMatching:query result:&result];
if (result) {
*outResult = CFBridgingRelease(result);
}
return status;
}

objective c memory manegment when returning objects from another object

I am having problem with understanding one concept of memory managment, because I am new to objective C. For instance lets say I have a class Bar and Foo.
in main function I call:
Foo *foo = [bar getFoo]; //In my bar method I return foo
[foo retain];
[foo callMethod];
[foo release];
I know this is right way to do it. But why do we have to retain it after we get it from another object, does not this mean returning object has retain count 0 ? so we have to reatin it to count 1 to use it? but if it has reatin count 0, how do we know it is still there. We can assume since it is the next line that increment retain count that the object memory wont be realocated, but what if we have multi-threading program?
When an class method returns an object, it will autorelease it so you don't have to bother; typically:
- (Foo *)getFoo
{
return [[_foo retain] autorelease];
}
If you are only using foo for the lifetime of the calling method you don't need to retain it, as it won't be autoreleased until next time through the run loop, so your code should actually be:
Foo *foo = [bar getFoo]; //In my bar method I return foo
[foo callMethod];
If, however, you want to hold foo for a while, outside the scope of the calling method, you need to retain it and then release it sometime later.
One more thing; the convention for getter method names is simply "name", so your setter should be setFoo and your getter would be foo. Keeping to the naming conventions is a good idea as it lets you know what a method does, in say 7 months time, and tools like static analysis understand the conventions.
The method getFoo doesn't return an object with a 0 retain count. It returns an object with a +0 retain count which means that:
the object's retain count is not null (otherwise, the object wouldn't exist)
and the retain count wasn't altered by the invocation of the method, or if it was, it was in a balanced way (with as many release/autorelease as retain/alloc/new/copy).
Thus the lifetime of the object entirely depends on where and how it is retained. We don't know how long the object will be valid as any method invocation could release the object.
For example, let's consider the following code:
id anObject = [anArray objectAtIndex:0];
[anArray removeObjectAtIndex:0];
The object anObject isn't retained any more by the array as we removed it. Therefore it may have been destructed (but maybe it wasn't because it is still used somewhere else).
Generally, when getting an object from a method (other that alloc, copy, new or retain), we can assume that:
either the object was retained then autoreleased,
either the object is retained by the object that returned it.
So we know the object foo is valid until we return from the current method/function or we invoke a method/function that alter the state of the object bar, whichever comes first. After that, it may have been destructed.
So in your case, you can safely omit the retain/release pair.
However, it is very difficult to guaranty that an object doesn't get released unless we know the implementation of every method we invoke. Therefore, retaining (then releasing) every single object we get is the safer approach and that's what the compiler will do when you enable ARC (Automatic Reference Counting).
But that would require you to write a lot of retain/release and your code would become difficult to read, understand and maintain. Moreover, the more code you write, the more bugs you get (unless you never write bugs).
In conclusion, you don't need to retain an object unless you have a reason to suspect it could vanish otherwise.

Why does it make sense to duplicate pointers in order to solve block-based retain-cycles under ARC?

Under ARC, a block is suspected to cause a retain cycle if you're using self inside the block, for example.
I've seen a workaround here, like this:
How can this workaround prevent a retain cycle?
weakRequest is just a pointer to the exact same object referenced by request. When ARC modifies the retain count of weakRequest or request, it's affecting the same object.
Then, in the block, there is this strange thing going on:
__strong ASIHTTPRequest *strongRequest = weakRequest;
This is the eqivalent to saying:
ASIHTTPRequest *strongRequest = weakRequest;
[strongRequest retain];
But again: It's one and the same object. Why all these different variable names? They're just pointers!
I never really cared much about blocks and tried to avoid them. But now this made me curious about what everyone is talking about when they say "a block captures the variables". Until today I thought this just means a block will retain every pointer you use which has been defined outside of the scope of the block, meaning that the block just retains whatever object you touch in it's scope.
I did this quick test:
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
[self.view addSubview:v];
v.backgroundColor = [UIColor orangeColor];
NSLog(#"self = %p", self); // 0x6a12a40
[UIView animateWithDuration:1.5
delay:0
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
UIViewController *my = self;
NSLog(#"my = %p", my); // 0x6a12a40
v.frame = CGRectMake(200, 200, 100, 100);
}
completion:nil];
Like you can see the object itself stays exactly the same. The block does not create a copy. So I can safely assume all the years of C and Objective-C knowledge are still valid:
ASIHTTPRequest *strongRequest = internetRequest;
ASIHTTPRequest *foo = strongRequest;
ASIHTTPRequest *bar = foo;
if (bar == internetRequest) {
NSLog(#"exact same thing, of course");
}
So what is going on there? How can this resolve a retain count if all that's happening is create different pointers to the same object? Why the extra mile of creating those pointers?
Wouldn't this be totally the same thing?
[request setCompletionBlock:^{
NSString *respondeString = [request responseString];
if ([_delegate respondsToSelector:#selector(pingSuccessful:)]) {
[_delegate pingSuccessful:responseString];
}
}];
There must be some secret about Objective-C which explains why duplicating pointers solves memory management problems here. It just doesn't make any sense to me.
It actually has nothing to do with ARC, but rather how blocks capture variables. The pointer is duplicated so that the variable captured by the block has the correct ownership qualifier.
weakRequest is just a pointer to the exact same object referenced by request. When ARC modifies the retain count of weakRequest or request, it's affecting the same object.
Right, they both point to the same object, but weakRequest has the __unsafe_unretained ownership qualifier, which means that when that variable is captured by the block, its retain count is unchanged.
If request were captured by the block then it would be retained and you would have retain cycle, regardless of whether you're using ARC.
The conversion back to a __strong pointer simply keeps that object alive for the duration that block execution.
Well, you specify a variable as __weak precisely so that the block won't retain it so that you can avoid a retain cycle. However, creating a __strong Variable inside the block and pointing it to the __weak variable is completely superfluous. You designate it as weak so that the block won't retain it. Creating a new one and designating it as __strong doesn't mean anything because there's no instance whereby the block will need to retain it. __strong is only a compiler keyword to tell ARC to retain the value if the need arrives...and ARC will never find that need since it's already been passed into the block. In the end, you could simply use the weakRequest variable and do away with the strongRequest variable.
You may be confused because there are two different things going on, to prevent two different problems. You quoted this line:
__strong ASIHTTPRequest *strongRequest = weakRequest;
That line does not prevent a retain cycle.
The (potential) retain cycle is one problem. The retain cycle would contain three objects: self, the ASIHTTPRequest, and the block. Use of the weakRequest variable breaks that cycle, because the block captures the weakRequest, which does not own the ASIHTTPRequest object. In reference count terms, assigning te weakRequest does not increment the reference count of the ASIHTTPRequest.
The line you quoted is there to prevent the other problem, which is created by solving the first problem. The other problem is a potential dangling pointer. Since weakRequest doesn't own the ASIHTTPRequest, there's a risk that during the execution of the completion block, all owners of the ASIHTTPRequest will release it. Then weakRequest will be a dangling pointer - a pointer to an object that has been deallocated. Any use of it is likely to cause a crash or heap corruption.
In the line you quoted, the block copies weakRequest to strongRequest. Because strongRequest is __strong, the compiler generates code to retain (increment the reference count of) the ASIHTTPRequest, and code to release it at the end of the block. This means that even if all other owners of the ASIHTTPRequest release it while the block is running, the ASIHTTPRequest will stay alive because the block has temporarily made itself an owner of the request.
Note that this solution to the dangling pointer problem is not thread-safe. If the owners of the request can release it from other threads while block is executing, there is a race condition that can still lead to a dangling pointer. This is why you should try to use __weak instead of __unsafe_unretained for weak pointers: __weak references can be copied to __strong references without a race condition.

Does this Objective-C code leak memory?

One thing I'm concerned about is I create two ints, but don't release them. Would it be better to make them NSIntegers?
-(void) flipCoin {
int heads = [headsLabel.text intValue];
int tails = [tailsLabel.text intValue];
if (random() %2 ==1 )
{
heads++;
}
else {
tails++;
}
headsLabel.text = [NSString stringWithFormat:#"%d", heads] ;
tailsLabel.text = [NSString stringWithFormat:#"%d", tails];
}
As sha notes, local variables get allocated in the current stack frame. As soon as the current function call returns, the stack gets "popped", and the memory occupied for the current call is not released so much as abandoned, until it is overwritten by the next call that gets pushed into that part of the stack.
So why do we have to release variables like this:
MyClass *myObject = [[MyClass alloc] init];
Well, you actually don't have to worry about "myObject". It's on the stack, just like your ints, and it will get cleaned up when the current call finishes.
What you have to worry about is the memory that myObject—which is a pointer—points to. It's off somewhere on the heap. Constructing an object involves asking the runtime for some semi-permanent place to put it; that process returns a memory address, which your pointer stores.
alloc and release are Objective-C idioms that largely replace C's malloc() and free() functions, but all of them ultimately are asking the computer to set aside memory on the heap, and all of that memory must ultimately be returned, either through an autorelease pool, a release message, or a free() call.
int is what is known as a primitive type. It is not a pointer to an Objective-C object so you cannot release it. You can't even send a message to it.
NSInteger is also a primitive type in the sense that it is a typedef to a primitive type (long usually). So you can't release that either.
What do you need to release? You need to release any object you obtained by sending new, alloc or a method containing copy. You also need to release objects to which you have sent retain. So all of the local variables in the following must be released:
-(void) foo
{
NSString* aString = [[NSString alloc] init];
NSString* aString2 = [aString copy];
NSString* aString3 = [someOtherString retain];
NSString* aString4 = [#"some string" copy];
}
NB due to implementation details, you would actually get away with not releasing the aString4 but you don't need to worry about it.
No. Your heads and tails variables are local and stored on the stack. This won't cause a leak. Your two NSString assignments near the bottom are created using convenience constructors and will be autoreleased for you.
All default datatypes (int, char, BOOL, etc) are automatically managed for you, and do not (and cannot) be released (for all intents and purposes).
NSIntegers behave likewise, as they are just signed ints (or signed longs on 64-bit machines).
Objects you initialize, however, like NSString or NSArray will usually have to be released (unless they are autoreleased, like the NSStrings at the bottom of your code). If you ever call -alloc and -init on something, you will have to later release it. If you ever doubt whether a method returns an autoreleased object, just read the documentation (it will tell you).
Also, if you want to read up on memory management, there are plenty of wonderful sources that will teach you (Google is a great place to start!), and if you ever think that your code leaks memory, run it through Instruments, and you'll be able to tell...