The correct way to free variables in Objective-c

I know that in Objective-c there is a very simple way to declare such variables:

NSArray* myArray; @property(retain) NSArray* myArray; @synthesize myArray; 

This way you can use self.myArray as a customization tool as well as a getter, storing the variable. However, it will also allow you to do one more thing that avoids the use of dealloc. As far as I understand, these two lines are the same:

 self.myArray = nil; [myArray release]; 

My question is which one is preferred? Are there any cases when one of them will work, and the other will not?

EDIT: Sorry, I mean release, not dealloc ...

+4
source share
4 answers

Updates below.

When working with (stored) synthesized properties, the best way to fulfill your dealloc responsibilities is to set the nil property. The reason I say this is the β€œbest” way is because it ensures that all contracts implied by the declaration of properties are fulfilled. For example, if your property was declared atomic (which will be, unless you specifically declare it non-atomic), the ONLY way to ensure that this property is canceled on dealloc using the same atomic guarantees is to set it to nil using the property in dealloc . It also means that it will behave correctly with respect to any observation of the key values ​​of your object. This can be important, especially if you are using Cocoa Bindings.

When performing native memory management for a (possibly private) instance variable without the corresponding property, there are several idioms. The simplest, but the most dangerous, is simply to free the iVar, for example:

 - (void)dealloc { [myArray release]; [super dealloc]; } 

This will cause the save on iVar to be released, but, as mentioned in other documents, it will exit the potentially obsolete pointer in order to potentially, if mistakenly, access obsolete or not held pointers that may exist, indicating the object is being freed . The next way is the idiom suggested by another answer:

 - (void)dealloc { [myArray release], myArray = nil; [super dealloc]; } 

An even safer, if more pedantic, idiom for this is:

 - (void)dealloc { id temp = myArray; myArray = nil; [temp release]; [super dealloc]; } 

This further limits the chances of an obsolete pointer reading by clearing the iVar before releasing the object that it points to. But due to the possibility of reordering instructions, even this is not a 100% guarantee against obsolete reading on all architectures.

While there is still more to say about concurrency and memory management, in the general case, if you have an @synthesized property installer, you should just use it in dealloc. This means that if you change the @property behavior, the dealloc behavior will be automatically correct for the @property declaration.

IMPORTANT NOTE: Using atomic properties! = Thread safety. (Actually, if you ask me that atomic properties are waste, but ...) For more details, see here .

UPDATE

This has recently been confirmed again, and although I support what I said here about atomic safeguards with synthesized conservation properties, and the other content in the original answer is valuable in itself, I feel the need to tell the other side of the story. Dave DeLong referred to some of these comments in the comments, but I decided it was worth adding a detail to the main answer.

I confirm that the only way to maintain atomicity guarantees is to set the nil property through setter. BUT you don't care, and here's why: If the object is dealloc ed, it means (if your graph of the object is correct) that there should not be any live references to this object. If there are no live references to the object, then no one can take care of the guarantees of atomicity of the operation that clears the property.

I also mentioned KVO in the original answer as the reason for using the setter in dealloc , but Dave DeLong mentioned KVO in the comments as counterpoint. He is right, and here's why: Again, if the object is dealloc ed, all KVO observers should already have been removed from it (again, there shouldn't be any live links, KVO or not). In fact, if this is not the case, it will not be long until you see a console message informing you that your object has gone away with the observations that still exist.

In short, while you cannot make atomic warranties equivalent to the synthesizer setter guarantees in dealloc , it never matters (and if that happens, something still doesn't work.)

+3
source

You should not call dealloc yourself (except in very unorthodox circumstances).

Instead of dealloc, you should call [myArray release] and let the released process take care of this for you.

Look here for more information than you would probably like to use the dealloc method as well.

+4
source

Whenever you have any instance variable that is an object, you must free it in the dealloc method. Therefore, in your case you should use

 - (void)dealloc { [myArray release], myArray = nil; [super dealloc]; } 
+1
source

Setting to zero in theory should have the same effect as the ivar release. However, you should never call the dealloc method. In the dealloc method, you sometimes see the idiom mentioned by David, in particular:

 [myArray release], myArray = nil; 

The reason for this is to avoid a very unlikely race condition where someone might try to access the released object before the dealloc is completed. When assigning the nil property, this allows the attempted access to fail gracefully.

+1
source

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


All Articles