Does ARC guarantee that an object is immediately canceled after the last strong link has disappeared?

In particular, whether such code will always work as intended (where MyResourceGuard is an object that locks an exclusive resource in its init method and releases the lock in the dealloc method):

NSLog(@"About to capture some exclusive resource."); { MyResourceGuard* guard = [MyResourceGuard new]; // Do something with the exclusive resource here. } // guard is out of scope, therefore its dealloc should have // been called right away and the resource should already // be free again at this point. 

I read in books and blogs that, unlike, for example, Java Garbage Collection, ARC destroys objects as soon as the number of links decreases to zero (and not at some time as I see fit), but I did not read it in any Apple official documentation. And if that were the case, why would we need the new @autoreleasepool keyword introduced with ARC?

From debugging, I have always seen that the dealloc'ed object is immediately, except when an exception occurs in the try-catch block, in which case dealloc was never actually called (is it a Mac error or just one of those scary C lenses?).

+4
source share
2 answers

No. You do not have deterministic destruction of ObjC objects based on objects, as your example shows.

For example, this program may cause deadlock:

 { MyResourceGuard* guard = [MyResourceGuard new]; } { MyResourceGuard* guard = [MyResourceGuard new]; } 

The best you can do if you need this function is to use the C ++ types ( SBRM, RAII ) - also available in Objective-C ++ (but not applicable to objc objects).

It is approaching, but you just need to wait until the reference count reaches zero for -dealloc to be called, and why the guarantees do not work (usually! = Always). This problem is actually very similar to why you will never rely or use -retainCount (where available). Examples: Autorelease pools, exceptions, changes to the execution script or ARC code, optimization of the compiler, use of implementations that have different code generation flags can lead to the extension of the objc object beyond the scope.

Update

an entire page on the ARC on the clang site is a good read on the topic - including details, warranties (and lack of warranties), but in particular:

6.1. The exact semantics of life

In general, ARC preserves the invariant that the stored pointer object held in the __strong object will be saved for the full formal lifetime of the object. Objects subject to this invariant have the exact semantics of life.

By default, local auto-storage time variables do not have the exact semantics of life. Such objects are simply strong links that contain values ​​of the type of the stored type of the object, and these values ​​are still fully subject to optimization according to the values ​​under local control.

Rationale: The strict application of exact life semantics is prohibitive. Many useful optimizations that could theoretically reduce the lifetime of an object will be impossible. Essentially, these promises are too many.

A local variable such as the owner of the stored object and automatic storage duration can be annotated with the objc_precise_lifetime attribute to indicate that it should be considered as an object with exact life semantics.

Rationale: However, it is sometimes useful to be able to force an object to be released at a specific time, even if that object does not appear to be used. This will probably be quite rare, the syntactic weight of an explicit request for this semantics will not be burdensome, and may even make the code more understandable.

Even if you use the objc_precise_lifetime attribute, it will apply to reference counting operations for this strong local variable, and not to the lifetime of the object.

+5
source

this code will always work. (or at least as long as the ARC works as it is now) A small example for an object's life cycle in ARC:

 { NSString *a = [[NSString alloc] init]; //object allocation a = nil; // object is deallocated as it was created in this scope NSString *b = [NSString string]; //method call which returns an object (always autoreleased) b = nil; // object is not deallocated as it was not created in this scope and is therefore autorelased } 
0
source

Source: https://habr.com/ru/post/1446456/


All Articles