NSError and __autoreleasing - objective-c

Can someone please explain to me the purpose of having __autoreleasing in the following sample code block?
- (void)execute:(NSError * __autoreleasing *)error {
// do stuff, possibly assigning error if something went wrong
}
I removed the __autoreleasing and everything still seems to compile/run fine. I started using obj-c post ARC so I never really learned/understood all those double underscore thingamajigs. I've read the ARC transition guide, but I don't fully understand their NSError example.

Consider how ARC works with variables - each reference variable has a mode (implicit or explicit): strong, weak, etc. This mode let's ARC know how to handle reads and writes to that variable; e.g. for a strong variable reading requires no additional action while writing requires releasing the existing reference in the variable before it is replaced by the new one. ARC needs to know the mode of any variable in order to function.
Now consider variables that themselves are passed by reference, e.g. for your execute you'll have a call along the lines of:
NSError *myError = nil;
...
[someObject execute:&myError]; // pass the variable itself by reference, not the variables value
and the body of execute will contain an assignment along the lines of:
- (void)execute:(NSError * __autoreleasing *)error
{
...
if (error != NULL)
*error = [NSError ...]; // assign indirectly via the reference to a variable
...
}
Now for that indirect assignment ARC needs to know the mode of the referenced variable so it knows how to read and write. That is what the __autoreleasing is in the declaration, it tells ARC that it has been passed a reference to a variable whose mode is autoreleasing, and that tells ARC how to read and write the contents of the variable. Remove the __autoreleasing and a default mode will be assumed, and in this case I'd suggest being explicit is certainly good.
The autoreleasing mode means the variable contains a reference which is not owned, reads should retain if necessary and writes can just write. It is used mainly for variables passed by reference.
You might notice that in the example above the variable myError has mode strong (implicitly) and yet it is passed by reference as autoreleasing - the compiler handles this automatically by introducing a temporary autoreleasing variable, copying without retaining the current reference in myError into it, and passing the temporary by reference as the argument to execute:. After the call returns the compiler does a normal assignment from the temporary to myError, which results in any old reference being released and the returned one retained.
For more details see Apple's Transitioning to ARC Release Notes
Followup to Comments
Q: Is __autoreleasing implicitly set?
A: Well Apple's document is not specific, but the Clang documentation says it is implicit for indirect parameters. As above I'd recommend being explicit, clarity is a Good Thing™.
Q: Does the placement matter?
A: Yes, and no... This is a C declaration, the stuff of quiz questions ("What does the following declare..."). The qualifier should be between the two asterisks as it is a pointer to a (variable of type) autoreleasing pointer to an object, but Apple state the compiler is "forgiving" without being specific of what it forgives. Play it safe, put it in the right place.
Q: Should you not test for error being NULL before doing the indirect assignment?
A: Of course you should, somewhere before you do the indirection. The code shown is just an outline and such detail was elided and covered by the ...’s. However as it has been raised a few times over the years maybe I elided too much, a suitable if has been added.

Related

Returning block that lives on the local stack

The clang analyzer can check for returning stack-based memory.
dispatch_block_t getPrintBlock (const char *msg) {
return ^{
printf("%s", msg);
};
}
raises this error: returning block that lives on the local stack
What does this error mean?
The error means you are returning a value which will be invalid after the method returns. This is not just an issue with blocks, consider:
- (int *) badMethod
{
int aLocalIntVariable;
return &aLocalIntVariable; // return a reference to aLocalIntVariable, but that variable is about to die...
}
Local variables are created when a method is entered, the place where they live is called the "stack". When a method returns those local variables are destroyed. You can return a value in such a variable, but you cannot return a reference to the variable itself - it will be invalid. You can pass a reference to a local variable to a method you call, as your local variable still exist in that case.
In your case you have created a block. Objective-C happens to create block values on the stack, i.e. effectively in an anonymous local variable, and refer to them using a reference. You can pass such a reference to a method you call, but you cannot return it - that anonymous local variable is destroyed just like any other.
However Objective-C provides you two ways to create a copy of a block value as an object, which lives on the "heap", and which will outlive its creator. First there is Block_copy which is a function:
<reference to heap allocated block> = Block_copy(<reference to stack allocated block>);
This is the original way to do this and is supported every - including in pure C code, blocks are part of C and not just Objective-C. The second way pretends the block is an object already and allows you to send the standard copy message:
<reference to heap allocated block> = [<reference to stack allocated block> copy];
If you are primarily an Objective-C person this second method probably feels more comfortable, but does blur the issue of why it is needed in the first place.
ARC helps here, in automating memory management it will automatically copy blocks from the stack to the heap (at least in current compilers, it may not work properly in earlier compilers) and so the programmer can ignore what is really an implementation detail.
Addendum: ARC
The last paragraph above was queried by #newacct and a long Q&A comment exchange resulted. In an attempt to make the information in that easier to follow we have both removed our comments and I have consolidated the information here as an addendum.
In understanding how ARC handles blocks two documents are useful:
Objective-C Automatic Reference Counting, in particular sections 3 (blocks are retainable object pointers), 3.2.3 (retainable object types are valid across return boundaries) and 7.5 (rules for when blocks are copied).
Transitioning to ARC Release Notes, in particular the FAQ item "How do blocks work in ARC?"
From these it can be determined that most of the time ARC will handle all copying of blocks from the stack to heap as part of its management of all object types.
The second reference highlights one case, that at least at the time the document was written, was not handled automatically. That case is where a stack allocated block is passed to a method parameter of type id, e.g. something like:
- (void) takeBlockWithTypeLoss:(id)block { ... }
[obj takeBlockWithTypeLoss:^{ ... }];
In such cases, at the time the document was written, ARC did not copy the block. If the called method then performs an operation which retains the passed block a problem occurs as the retain value is not on the heap. (Note that the block needs to be stack allocated for a problem to occur. Literal blocks which do not reference variables in their environment are statically allocated, also a literal block which is first stored in a local variable with default strong ownership and then passed to the method will be copied.)
This case is an example of type loss, a value known to be a block type is passed as id loosing type information. The compiler can always determine such points, so why does (or did..) ARC not copy the block? The answer given in the past is simply one of efficiency, the copy may not be required and lots of unneeded copies is a performance hit.
However the current compiler (Xcode 4.6.1) appears to handle this one remaining case, at the point of type loss a block is copied to the heap. If anyone can show this is now documented (or you are confident that your compiler handles this case e.g. by coding a check) then it would appear Block_copy() (or [block copy]) can be relegated to history, if not then when type loss occurs it should be used.
Addendum: June 2013
As revealed by this question there is a case that Xcode 4.6.3/Clang 4.2 does not handle. When a block is passed as one of the variable arguments to a variadic method then the compiler does not automatically promote a stack block to the heap. This is a subcase of type loss mentioned above.
So there is a case current compilers do not handle, which suggests a reason why the compiler supporting more than the specification is undocumented - that support is incomplete (though these is no theoretical reason that it needs to be).
So as before, if there is type loss then the compiler may not handle block promotion automatically (but this can be tested for if so desired), cases not involving type loss are handled automatically as per the specification.
(BTW. The older question mentioned in a comment to the question above is now one of the cases covered by the specification and handled correctly by the compiler.)
You need to make a copy of the block to move it to the heap.
i.e. something like:
dispatch_block_t createPrintBlock (const char *msg) {
return Block_copy(^{
printf("%s", msg);
}) ;
}

__strong or __weak (or something else) for parameter when overrideing -isEqual:?

I'm overriding - (BOOL) isEqual:(id)object in a custom class.
Out of the 4 choices, which are __weak, __strong, __autoreleasing, and __unsafe_unretained, which should I be using on the parameter for the isEqual: method signature?
I'm thinking this is where the problem is, since when I'm trying to add an instance of my class to a NSMutableDictionary, I'm getting an EXC_BAD_ACCESS(code=2, address=0x10) at the declaration of the method.
In other words, the line at which the debugger gets the EXC_BAD_ACCESS is:
- (BOOL) isEqual:(id __strong)object {
before any of the method body is executed.
The correct answer was "If you're getting bad access, then you're trying to read or write to an area that doesn't have what you think it has in it.", per #Dustin Rowland in the comments.
By default, ARC uses __strong, which means that the argument is held via a retain/release for the duration of its use inside the method. To lead to EXC_BAD_ACCESS, an object (either the argument itself, or any other object used in the method calls inside the isEqual: implementation) has to be over-released when accessing it. This cannot be fixed by changing the qualifier.
Sidenote: Be careful though by expecting to see anything to change when you change the qualifier. The compiler optimizations may decide that it is safe to skip some calls. For example, add the following code to a file and look at the assembly (Product -> Generate Output -> Assembly File) for Archiving (which uses -Os).
- (void)logObject:(id)o
{
NSLog(#"%#", o);
}
- (void)call
{
id o = [[NSObject alloc] init];
[self logObject:o];
}
Although the parameter of logObject: is the default __strong, no retain/release is done in the assembly output. Changing the parameter of -logObject: to __strong, __weak, __unsafe_unretained or __autoreleasing gives exactly the same assembly output. If you duplicate the line with the NSLog however, the assembly code changes for the different type qualifiers.

How to declare a pointer member variable in a class with ARC in Objective C?

I have a class RemoteImageLoader which has a method loadImage:
- (void) loadImage: (NSString*) url setTarget:(NSData **)target;
I used a NSData** here because I need to indirectly return NSData* , just like some typical method:
- (BOOL)save:(NSError**)
since the method will actually invoke another asynchronous method, I have to save the target as a member variable so I can access it later. but when I define a NSData ** member variable:
#interface RemoteImageLoader : NSObject
#property NSData** target;
#end
the compiler complains that "Pointer to non-const type 'NSData*' with no explicit ownership". I've done some search on google, but find no answer of it. Could anyone help me with this? Thanks a lot
and I've tried to replace the declaration to
#interface RemoteImageLoader : NSObject
#property NSData * __autoreleasing * target;
#end
but the problem still exists
The ARC Transition Notes recommend you declare indirect pointers to NSData and NSError objects in your case with __autoreleasing, like (NSData * __autoreleasing *)target;
__autoreleasing is known as a lifetime qualifier which tells the compiler to return an autoreleased instance of the object.
Because of this, a rewrite of your method signature is required.
- (void) loadImage: (NSString*) url setTarget:(NSData* __autoreleasing *)target;
Be warned, __autoreleasing objects are extremely short lived. Declare your NSData** as __strong to override the default __autoreleasing for a longer lifetime.
I think your method signature is going to cause trouble. A caller is very likely to assume that the pointed-to pointer is filled in as soon as your method returns. Similarly, they are very likely to pass the address of a stack variable which won't be valid for long. Lastly, your method provides no means for the caller to know when the pointed-to pointer has been filled with a value.
You are probably better off taking a completion block from the caller. The completion block will receive an NSData pointer as an argument. Something like:
- (void) loadImage: (NSString*) url completionHandler:(void (^)(NSData* data))block;
This also mirrors the underlying framework API I presume you're using, which is always good for reducing "impedance mismatch".
As for the specific narrow issue you're encountering from the compiler, I suspect the issue is that the compiler can't know if it should emit retains and releases when you assign to *target. It wants you to explicitly declare the ownership characteristic of the pointed-to pointer. I can't check at the moment, but I guess that declaring it as __strong NSData** target would work. That is, it's not interested in whether target owns what it's pointing at, since one can't own a pointer. It's interested in whether the NSData* pointer to which target points owns the NSData object to which it points.
I can't be sure what you are trying to do without seeing your code, but why are you trying to create a pointer to an NSData object (Which is a pointer to NSData). Because you are creating a pointer to a pointer which is probably why you are getting the error. Try removing one of the pointers and see what happens.
Generally, when you do this sort of thing outside of ARC you do something like:
NSData* returnedParm;
[someObj doSomething:&returnedParm];
on the caller's side. I don't see your equivalent of my returnedParm above. (I've never tried this with ARC, but I'd think the basics would have to be similar.)
Declaring a property as NSData** is declaring a pointer to a non-object and it would not be retained (because there's no object to retain).
My guess is that you should prototype your function as:
-(void)doSomething:(NSData* __autoreleasing*)theReturnParm
and assign to it inside that function using *theReturnParm = something;.
Then on the calling side you'd have your returnedParm as an autoreleased value (so if you want to preserve it you should relatively quickly assign it to a strong pointer).

Under ARC, are Blocks automatically copied when assigned to an ivar directly?

Assume the following code under ARC,
typedef void (^MyResponseHandler) (NSError *error);
#interface MyClass : NSObject
{
MyResponseHandler _ivarResponseHandler;
}
- (void)myMethod:(MyResponseHandler)responseHandler
{
_ivarResponseHandler = responseHandler;
...
}
Question: Is the block automatically copied to the heap when assigned to the ivar?
My previous question implied that it is copied when assigned through a #property. But, today I used the above code and received an EXC_BAD_ACCESS that was fixed by changing to
_ivarResponseHandler = [responseHandler copy].
Edit: My previous answer was likely wrong.
Some selected excerpts from the ARC docs say:
3. Retainable object pointers
A retainable object pointer (or retainable pointer) is a value of a retainable object pointer type (retainable type). There are three kinds of retainable object pointer types:
block pointers (formed by applying the caret (^) declarator sigil to a function type)
4.2. Semantics
Assignment occurs when evaluating an assignment operator. The semantics vary based on the qualification:
For __strong objects, the new pointee is first retained; second, the lvalue is loaded with primitive semantics; third, the new pointee is stored into the lvalue with primitive semantics; and finally, the old pointee is released. This is not performed atomically; external synchronization must be used to make this safe in the face of concurrent loads and stores.
4.4.1. Objects
If an object is declared with retainable object owner type, but without an explicit ownership qualifier, its type is implicitly adjusted to have __strong qualification.
7.5. Blocks
With the exception of retains done as part of initializing a __strong parameter variable or reading a __weak variable, whenever these semantics call for retaining a value of block-pointer type, it has the effect of a Block_copy. The optimizer may remove such copies when it sees that the result is used only as an argument to a call.
So I think the answer is maybe, depending on the optimizer.
Your problem and solution indicate that my answer to your other question was probably wrong. I based it on the last paragraph of section 7.5 of the clang Objective-C Automatic Reference Counting documentation:
With the exception of retains done as part of initializing a __strong parameter variable or reading a __weak variable, whenever these semantics call for retaining a value of block-pointer type, it has the effect of a Block_copy. The optimizer may remove such copies when it sees that the result is used only as an argument to a call.
I took “these semantics” to mean the whole document, but if “these semantics” to refers to only section 7.5, then ARC only inserts a Block_copy for a block that is captured by a block.

Objective-C in,out,inout,byref,byval, .. and so on. What are they?

I discovered something unfamiliar while reading Objective-C manual for #encoding.
Table 6-2 Objective-C method encodings
Code Meaning
r const
n in
N inout
o out
O bycopy
R byref
V oneway
The only thing I know is oneway. What are the others?
Those are annotations for method parameters and return values which were used by Distributed Objects. I say were because apparently there’s no sign of them in Apple’s documentation any longer. There used to be a Remote Messaging section in The Objective-C Programming Language document, which is still referenced by the Distributed Objects Programming Topics document.
in: argument is an input argument only and won’t be referenced later
out: argument is an output argument only, used to return a value by reference
inout: argument is both an input and output argument
const: the (pointer) argument is constant
bycopy: instead of using a proxy/NSDistantObject, pass or return a copy of the object
byref: use a proxy object (default)
Beyond Distributed Objects, one of these annotations appears to be used by ARC. I came across the following in clang's description of passing to an out parameter by writeback:
If the parameter is not an Objective-C method parameter marked out, then *p is read, and the result is written into the temporary with primitive semantics.
This has to do with methods like - (BOOL)executeWithError:(out NSError **)error.
Ignoring the out keyword, ARC has a well-defined behavior of treating by-reference object passing as __autoreleasing, so ARC treats the error parameter as having a type of NSError * __autoreleasing *. If you use an otherwise qualified variable, ARC will add a temporary autoreleasing variable pass into the function (for coherence):
Original code
NSError *error;
[obj executeWithError:&error];
Pseudotransformed code
NSError * __strong error;
NSError * __autoreleasing temp;
temp = error;
[obj executeWithError:&temp];
error = temp;
With the above code, the line temp = error would be unnecessary if we could somehow know that temp will never be read. This is where the out annotation comes into play. Per the quoted description if out is missing the compiler must add the line temp = error but if it does contain out it can exclude the line and make the code just a little bit smaller/faster. With out the transformed code becomes:
NSError * __strong error;
NSError * __autoreleasing temp;
[obj executeWithError:&temp];
error = temp;
Of course, if you're that worried about binary size and speed, you should just code the following:
NSError * __autoreleasing error;
[obj executeWithError:&error];
It is entirely possible that these annotations are used other places throughout the compiler and runtime, and may be used in more places in the future. Personally, I like using out as a hint to other developers that I'm not going to read the value.
Incase anyone has stumbled across this post and has the same confusion as me, the 'in' argument can also be a keyword that represents fast enumeration. See here for more details.
You can read the Objective-C runtime sources http://www.opensource.apple.com/source/objc4/objc4-437.1/ to understand what these annotations mean.