Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 237 Vote(s) - 3.57 Average
  • 1
  • 2
  • 3
  • 4
  • 5
In which situations do we need to write the __autoreleasing ownership qualifier under ARC?

#1
I'm trying to complete the puzzle.

`__strong` is the default for all Objective-C retainable object pointers like NSObject, NSString, etc.. It's a strong reference. ARC balances it with a `-release` at the end of the scope.

`__unsafe_unretained` equals the old way. It's used for a weak pointer without retaining the retainable object.

`__weak` is like `__unsafe_unretained` except that it's an auto-zeroing weak reference meaning that the pointer will be set to nil as soon as the referenced object is deallocated. This eliminates the danger of dangling pointers and EXC_BAD_ACCESS errors.

But what exactly is `__autoreleasing` good for? I'm having a hard time finding practical examples on when I need to use this qualifier. I believe it's only for functions and methods which expect a pointer-pointer such as:

- (BOOL)save:(NSError**);

or

NSError *error = nil;
[database save:&error];

which under ARC has to be declared this way:

- (BOOL)save:(NSError* __autoreleasing *);

But this is too vague and I'd like to fully understand *why*. The code snippets I find place the __autoreleasing inbetween the two stars, which looks weird to me. The type is `NSError**` (a pointer-pointer to NSError), so why place `__autoreleasing` inbetween the stars and not simply in front of `NSError**`?

Also, there might be other situations in which I must rely on `__autoreleasing`.
Reply

#2
Following up on Macmade's answer and Proud Member's follow up question in the comments, (would have also posted this as a comment but it exceeds the max character count):

Here is why the variable qualifier of __autoreleasing is placed between the two stars.

To preface, the correct syntax for declaring an object pointer with a qualifier is:

NSError * __qualifier someError;

The compiler will forgive this:

__qualifier NSError *someError;

but it isn't correct. See [the Apple ARC transition guide](

[To see links please register here]

) (read the section that begins "You should decorate variables correctly...").

To address to the question at hand: A double pointer cannot have an ARC memory management qualifier because a pointer that points to a memory address is a pointer to a primitive type, not a pointer to an object. However, when you declare a double pointer, ARC does want to know what the memory management rules are for the second pointer. That's why double pointer variables are specified as:

SomeClass * __qualifier *someVariable;

So in the case of a method argument that is a double NSError pointer, the data type is declared as:

- (BOOL)save:(NSError* __autoreleasing *)errorPointer;

which in English says "pointer to an __autoreleasing NSError object pointer".
Reply

#3
The [definitive ARC specification][1] says that

> For __autoreleasing objects, the new pointer is retained, autoreleased, and stored into the lvalue using primitive semantics.

So for example, the code

NSError* __autoreleasing error = someError;

actually gets converted to

NSError* error = [[someError retain] autorelease];

... which is why it works when you have a parameter `NSError* __autoreleasing * errorPointer`, the called method will then assign the error to `*errorPointer` and the above semantics will kick in.

You could use `__autoreleasing` in a different context to force an ARC object into the autorelease pool, but that's not terribly useful since ARC only seems to use the autorelease pool at method return and already handles that automatically.

[1]:

[To see links please register here]

Reply

#4
You're right. As the official documentation explains:

> __autoreleasing to denote arguments that are passed by reference (id *) and are autoreleased on return.

All of this is very well explained in the [ARC transition guide][1].

In your NSError example, the declaration means `__strong`, implicitly:

NSError * e = nil;

Will be transformed to:

NSError * __strong error = nil;

When you call your `save` method:

- ( BOOL )save: ( NSError * __autoreleasing * );

The compiler will then have to create a temporary variable, set at `__autoreleasing`. So:

NSError * error = nil;
[ database save: &error ];

Will be transformed to:

NSError * __strong error = nil;
NSError * __autoreleasing tmpError = error;
[ database save: &tmpError ];
error = tmpError;

You may avoid this by declaring the error object as `__autoreleasing`, directly.

[1]:

[To see links please register here]

Reply

#5
To be short: this is only for compatibility with MRC.

Apple have made agreement that in own libraries objects returned by `**` are always autoreleased. So `ARC` code will work fine with old binaries (for example if you have deployment target iOS 4) and vise versa `MRC` code will work fine with `ARC` binaries.

So in conclusion:
* You should never use `__autoreleasing`: compiler will automatically add it where needed
* If you are not going to support MRC code, then you should use `* __strong *` everywhere. It will save from crashes of family:

@autoreleasingpool {
*autorelesingOut = [@"crash maker" mutableCopy];//NSString * __autoreleasing *autorelesingOut;
*strongOut = [@"it's ok" mutableCopy];//NSString * __strong *strongOut;
//App will crash if autorelesingOut will be referenced outside of this autoreleasepool
}

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through