Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is Apple warning against in ARC documentation caveat about pass by reference?

In Apple's documentation about ARC, they make a point of spelling out a problematic scenario in which ARC will generate a boilerplate temporary variable behind the scenes. Search on "The compiler therefore rewrites":

https://developer.apple.com/library/mac/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html

The gist of the warning seems to be that because the stack-based variable is "strong" and the by-reference parameter to the called method (performOperationWithError:) is autoreleasing, ARC will generate a temporary local variable to serve the memory management needs of the autoreleasing variable. But because the temporary variable is assigned to the strong variable in the boilerplate example, it seems as though from a client's point of view there is no risk.

What exactly is the documentation taking pains to warn us about here? What is the risk as either a client or as an implementor of a method that may be called in this way (with an autoreleased, return-by-value parameter)?

like image 839
danielpunkass Avatar asked Feb 28 '14 05:02

danielpunkass


3 Answers

It's only a warning about less than ideal performance. In the rewritten code, the NSError pointed to by "tmp" comes back autoreleased, is retained when assigned to "error", and then is released again when "error" goes out of scope.

If you change the declaration in the original code to: NSError __autoreleasing *error;

If you do this, there is no assignment to a temp, and that implicit retain and then release no longer occurs. (The NSError object itself is still valid for exactly as long as it was before, since it is still in the autorelease pool.) So the documentation is warning you that if you use the "wrong" variable qualifier that it can cause extra retain count munging that wouldn't otherwise be required.

Also note that with either version of the code: Because the variable in question is passed by reference and isn't the return value from -performOperationWithError:, there isn't the opportunity to do the magic stack walking trick that ARC can do to save the object from going into the autorelease pool in the first place.

like image 151
gregomni Avatar answered Oct 18 '22 22:10

gregomni


I think it’s to prevent confusion if you start looking at the values passed into the method. In their example, if I set a breakpoint on the line that calls [myObject performOperationWithError:&tmp]; and type p error, I’ll see the address of it. But if I step into -performOperationWithError: and type p error, I’ll get a different value—inside the method, error points to that temporary value.

I can see a situation where some poor sap is trying to debug something tricky with ARC where the pointer changing as it gets passed into the method would be an extremely confusing red herring.

like image 38
Jeff Kelley Avatar answered Oct 19 '22 00:10

Jeff Kelley


My guess: If you made assumptions about the memory referenced by the output parameter, e.g indexing off the pointer, you might be surprised.

like image 5
Jon Gary Avatar answered Oct 18 '22 22:10

Jon Gary