Why do I have to call CFRelease after __bridge_transfer? - objective-c

CFArrayRef refAllPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
NSArray * arPeople = (__bridge_transfer NSArray*)(refAllPeople);
When I analyze it says potential memory leak.
Let me try to understand. refAllPeople have 1 ref count.
Then I do _bridge_transfer. That moves ownership to me. To be more exact, it has arPeople pointing to it and add the retain count by 1. Then the retain count is reduced by one because _bridge_transfer is equivalent with (__bridge) followed by CFRelease.
So,
Why the memory leak complaint?

Your understanding is correct. __bridge_transfer will take refAllPeople back to the world of NSObject where ARC operates and you don't have to explicitly call CFRelease.
I believe it's a static analyser mistake.
From the docs (thanks Carl)
(__bridge_transfer T) op casts the operand, which must have non-retainable pointer type, to the destination type, which must be a retainable object pointer type. ARC will release the value at the end of the enclosing full-expression, subject to the usual optimizations on local values.

It's embarrassing. There is no memory leak :). Somehow I misread the error message and think all blue things means memory leak.
I am glad that my understanding of bridge_transfer is correct and I hope it's useful for everyone.
+1 for others that have answered this :)

Related

ARC __bridge modifiers demystified

I was asked recently by one of my friends about the new bridge modifiers that became active under ARC. He asked me if I knew which ones to use in specific times and what the difference between the different __bridge modifiers were. He asked me,"so how do they work, when do I use them, how do I use them , and how do they work "under the hood" "?
Note: This was supposed to be a "Share your knowledge" type of question, where I answered the question myself, but I'm not sure I set it up properly.
Because I learned what they were and how they operated just recently, I want to share with anyone else who wishes to learn about the __bridge modifiers under ARC which can be a source of confusion due to the fact that toll-free bridging used to be accomplished with a simple cast.
It used to be that if you wanted to, say, cast your NSArray object to a CFArrayRef for any purpose, it could be done with a simple cast like so:
NSArray* myArray = [NSArray alloc]initWithObjects:....]; //insert objects
CFArrayRef arrayRef = (CFArrayRef) myArray;
In this case, maybe you had an NSArray of colors and needed to cast it to CFArrayRef for using it with CoreGraphics to draw a gradient.
However with ARC, this will no longer work for you and you will receive this error:
Well what the heck does this mean!?!
Well it turns out, ARC doesn't like it when you do this kind of cast and will even give you a few "Fix it" solutions, which all seem to have that same __bridge keyword in them, so let's get right to them!
Under ARC we have 3 main __bridge modifiers:
__bridge
__bridge_retained ( which is partnered by the CFBridgingRetain function)
__bridge_transfer (which is partnered by the CFBridgingRelease function)
So we'll begin with __bridge. What is it? __bridge is just another way of saying: "Hey compiler, just give me my darn casted object!". The compiler will be happy to do so and return to you a casted object of your liking!
However, because you wanted a "freely" casted object like that, YOU are still responsible of releasing the memory for the originally allocated object. In this case, if I were to do this:
NSArray* myArray = [NSArray alloc]init];
CFArrayRef arrayRef = (__bridge CFArrayRef) myArray;
I am still responsible for releasing the myArray memory because it was the originally allocated object. Remember, __bridge just tells the compiler to perform the cast!! And because I am compiling under ARC, I don't explicitly have to call [-release] on the myArray object, ARC will do it for me!
Note, that the __bridge modifier works both ways! (Hence, toll-free bridging) and you can just as easily cast a CF object to an NS object the same way ( that is toll-free bridgeable!) like so:
CFArrayRef arrayRef; // allocate this arrayRef and give it a value later on
//... amazing code.....
NSArray* myArray = (__bridge NSArray*)arrayRef;
But since the CF object would be the originally allocated object, I must call CFRelease(whatever);
Now let's move on to __bridge_retained and its partner in crime CFBridgingRetain() . This __bridge modifier is geared EXPLICITLY towards transferring the ownership of an NS object TO A CF OBJECT (So we'll be expecting to manually CFRelease(whatever) this due to it being a CF type object)
Meaning, if I were to do my old scenario again, but this time with __bridge_retained:
NSArray* myArray = [NSArray alloc]initWithObjects:....]; //insert objects
CFArrayRef arrayRef = (__bridge_retained) myArray;
the arrayRef object now has explicit ownership of the memory that used to be owned by the myArray pointer. Because now the CF type has ownership, I must release it myself using CFRelease(whatever);
So what role does the CFBridgingRetain() function play in all this chaos? It plays the same exact role as doing the cast we just talked about! Let's take a look at the function prototype for CFBridgingRetain:
CFTypeRef CFBridgingRetain(id x);
We can see, it pretty much just simplifies the whole (__bridge_retained) notion into one function! We're gettting back a CF object after "inputting" an NS type object! Radical! Yes, I know this is awesome! Too much coolness to take in one sitting! And yes, it also performs the memory "ownership" transfer.. how awesome!
And last, but by no means least, __bridge_transfer and the almighty CFBridgingRelease() !
__bridge_transfer works almost like the opposite of __bridge_retained. The __bridge_transfer modifier transfers the ownership of a CF object type to an NS object type.
So let's refer to the example that's been used throughout this to dissect it:
NSArray* myArray = [NSArray alloc]initWithObjects:....]; //insert objects
CFArrayRef arrayRef = (__bridge_retained) myArray;
// at this point, arrayRef holds the ownership
// Let's add this new line to change things up a bit:
NSArray* otherArray = (__bridge_transfer NSArray*)arrayRef;
So what does this awesome little program that we just wrote exactly do?
Step 1: We allocated an NSArray
Step 2: We passed the ownsership of the array to the arrayRef object
// Before we continue to step 3, let's understand at this point arrayRef is the owner
Step 3: We re-transfer the ownership that USED to be owned by arrayRef back to an NSArray*
Because at this point, the otherArray pointer is the owner, it would seem sort of natural at this point to say [otherArray release] when we're done, right? Well this is where ARC kicks in and will take care of releasing that array for you!
And did you know it gets cooler? This __bridge modifier's awesome partner in crime:
CFBridgingRelease()
makes it that much cooler! CFBridgingRelease has this function prototype:
id CFBridgingRelease(CFTypeRef x);
And we see, this is exactly the same thing that happens when we cast with __bridge_transfer. And this function also transfers the ownership to the NS object! This is just fantastic!
Using the CFBridgingXXX functions maybe can make a little more sense at first, due to the fact that many objective-c programmers still have the notion of the NARC rule:
Everything that has been called with:
N ew
A lloc
R etain
C opy
must have a balancing -release call
So doing this:
NSArray* myArray = [[NSArray alloc]init];
// there's the A of NARC!
//(cleaned by ARC)
CFArrayRef arrayRef = CFBridgingRetain(myArray); // there's the R of NARC!!
//NSArray* other = CFBridgingRelease(arrayRef); // cleaned up by ARC
Can make the process of learning the __bridge casts easier due to the fact that the retain was matched with a release
If all this still may be confusing, think of it this way: You are a pointer to any NS object type. For the sake of consistency, let's say you're an NSArray pointer, that right now isn't pointing to anything. So you can sort of imagine that you, as the nil pointer, are standing in a bathroom with the lights turned off. ( The lights turned off represents that you aren't pointing to anything).
Then, later on in code, your programmer decides to assign you to a new NSArray. i.e, he/she says this:
you = [[NSArray alloc]init];
Suddenly, the lights in the bathroom you were standing in, have turned on! You're pointing to an object! Now in normal program execution, when you're done using the object, you release it. So in this case, when you're done using the bathroom, you turn the lights off.
But the program you're in, unfortunately, isn't very "normal". The programmer decided to use some CoreFoundation objects! Bleh!
And he writes this line of code:
CFArrayRef other = (__bridge_retained CFArrayRef) you;
So now what happens is that, another person walks into the bathroom at the same time you leave. Out of politeness, you don't turn the lights off because there's another person using the restroom and is responsible for turning the lights off when he/she leaves
In this case, because the new owner of the restroom is a CF object, the programmer must manually release it.
But what if he/she were to write this:
CFArrayRef ref = (__bridge CFArrayRef) you;
what happens here is that, another person just barged into the same restroom as you without even asking! How rude! On top of that he expects you to clean up after him too! So you, being a gentlemen/lady turn off the lights when both of you finish.
However, since you are an NS type object, ARC comes and cleans it for you :)
And finally, what if the programmer writes this:
you = (__bridge_transfer NSArray*)arrayRef;
What happens here is the exact opposite of the first scenario. Instead of you leaving the restroom at the same time as someone enters, you're the one who enters while the other person leaves
The same memory management rules apply. Since you took over "owning" the restroom, you must manually turn off the lights. And because you're an NS type object, ARC will do it for you... again :) Isn't ARC such a beauty!
I know this may seem a bit intimidating and confusing at first, but just work your way through it, read it again and you'll find out how incredible this ARC mechanism works!
Thanks everyone for reading! Hope this helped :)
Thanks to #rob mayoff and # Krishnabhadra for
all the extra help and suggestions!

ARC and __unsafe_unretained

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)

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;
}

copy an NSMutableString instance returns retainCount of -1

Can someone explain why the last line prints out -1? It happens when copy is called on a NSMutableString, I expect the returnCount of strFour to be 1, since an immutable copy should be returned.
NSMutableString *str =[NSMutableString stringWithString:#"hi"];
NSLog(#"new instantiated variable has a retain cout:");
NSLog(#"%d",[str retainCount]); //1, str is a pointer, its value is a memory address
NSMutableString *strFour =[str copy]; //receiver str is mutable, copy returns an immutable
NSLog(#"%d",[strFour retainCount]); ////strFour s retain count should be 1, but it had a retain count of -1
Thanks a lot.
Never bother looking at the retain count of an object. It is always meaningless to do so. The retain count is likely affected by optimisations “under the hood”. These optimisations rely on the fact that your code follows the Cocoa Memory Management Guidelines. Just worry about sticking to those guidelines and don't bother looking directly at the retain count.
One reason why it could be (-1) because the string “hi” may be cached somewhere and your copy is referring to the cached string. Keep in mind that the retain count is actually an unsigned integer. The documentation dor -retainCount says that for objects that never get released, the retain count should be UINT_MAX (which when printed as a signed decimal will come out as “-1”).

Why does sending retainCount to #"Hi" return -1?

The method retainCount is supposed to return an unsigned integer.
Why then, does [#"Hi" retainCount] return -1?
The simple answer is that because #"Hi" is a string literal, it will always be sitting around in the binary executable image, and will never "go away", thus retain/release have no effect, and you're seeing UINT_MAX (which looks like -1 when printed out signed eg with %d). (See Pete Kirkham's answer about NSObjects having these semantics).
Beyond this, it's useful to know that although #"Hi" behaves like an NSString*, it's actually a compiler-created instance of the class CFConstantString (or possibly NSConstantString, my debugger doesn't agree with some documentation), which wraps the literal string data and gives you the NSString* interface on it. But the compiler knows that these strings are special and can't ever get cleaned up, so they will always have a retainCount of UINT_MAX (-1)
According to Apple's NSObject documentation, it should return UINT_MAX for objects which never get released. If you print UINT_MAX as a signed int, you typically get -1, which may be what you're doing - how are you outputting the value?
Don't ever rely on the retainCount method. Cocoa makes all sorts of optimisations behind-the-scenes which makes the retainCount method unreliable and useless. Even Apple discourages using it. Stick to the memory management rules set out for Cocoa and you'll never need to know the retainCount of any object.
The only difference between signed and unsigned integers is how you interpret the value. If read -1 as an unsigned int you'll find that it is the maximum value for an unsigned int.
For example: NSLog(#"%u", [#"Hello" retainCount]);
The reason it's such a large value is because constant string objects are never deallocated.
#"Hello" is not required to release with code ,
just be care for the object was create by "alloc" other no memory leak issue