When deallocing a refrence I've seen release and dealloc being used for example
-(void)dealloc
{
[foo release];
[nar dealloc];
[super dealloc];
}
My question is when is release to be used and when is dealloc to be used?
Thanks
Never call dealloc except as [super dealloc] at the end of your class's dealloc method. The release method relinquishes ownership of an object. When a Cocoa object no longer has any owners, it may be deallocated — in which case it will automatically be sent a dealloc message.
If you're going to program Cocoa, you need to read the Memory Management Guidelines. It's incredibly simple once you get over the initial hump, and if you don't understand what's in that document, you'll have lots of subtle bugs.
The dealloc statement in your example is called when the object's retain count becomes zero (through an object sending it a release message).
As it is no longer needed, it cleans itself up by sending a release message to the objects that it is holding on to.
You're never supposed to call dealloc explicitly (unless it's [super dealloc] within the dealloc method, but that's the only exception). Objective-C handles memory management via reference counting, so you're simply supposed to match your allocs/retains with releases/autoreleases and let the object deconstruct itself.
Related
I am trying to do project with Manual Memory Management in Objective-c. I disabled ARC. I developed custom data structure LinkedList how can I dealloc this data structure? Should I use dealloc or release for dealloc object? When I tried dealloc it return me error. Is any memory profiler in xcode?
With manual memory management you call release when you no longer require an object you own.
The dealloc method of an object is called by the system before it is destroyed, it can be used to do cleanup. A dealloc method in manual memory management must call [super dealloc] - this is different from ARC where the super method must not be called.
HTH
I recently came across this blog post where two flavors of instance variable deallocation are discussed. To give you a summary:
The first approach
- (void)dealloc {
[instanceVar release];
[super dealloc];
}
is considered to leave a pointer alive until the method returns. This can lead to undefined behavior.
The second approach
- (void)dealloc {
[instanceVar release], instanceVar = nil;
[super dealloc];
}
is considered to be more stable for production code because the instaceVar is set to nil.
OK. Here is the question you've been waiting for:
Are both solutions the same? Or does the comma separation of expressions make them atomic?
The blog post you link to is from 2010.
The more interesting point nowadays is that you have to do neither. If you use ARC, then you can't send a release message to objects.
The setting of nil after release was to prevent non-retained objects to be sent messages after they were deallocated and cause a crash. I say non-retained objects, because if they were retained objects, they wouldn't (shouldn't) be released unknowingly. Again, with ARC (as long as you aren't using ARC-lite) you can mark non-retained objects as weak, and weak pointers auto-zero; i.e. when the object they point to is deallocated, the pointer is set to nil.
So the second case, with pointers being set to nil after a dealloc, is considered safer at run-time, but you don't have to worry about it now, as ARC handles that for you.
The comma doesn't make it atomic, but there should only be one thread invoking dealloc anyway or else you have much, much larger problems on your hands. Setting instanceVar to nil is unnecessary, it isn't safer, because if there is a bug in your program that somehow uses the dangling value in instanceVar it will only manifest differently depending on whether it is nil or something else, either way, there is a bug, because nothing should be relying on that value.
With ARC this is even less of an issue. A dealloc method in ARC is only used to release non-ARC-controlled resources, everything else is automatically handled for you.
It seems that in Objective-C, the method that is responsibile for memory allocation (like malloc() in C), is -[NSObject alloc]. What about freeing that memory? Is that done by -[NSObject dealloc]? Is that why in our own class's dealloc, we must call [super dealloc] last, instead of first?
I ask because I don't understand why, if I put [super dealloc] first, and release an object using [_bar release] on the next line, I don't get a segmentation fault. After [super dealloc] runs, if it frees the object's memory, _bar should already be a memory chunk that doesn't belong to the process.
I think you are saying, you have this code:
- (void)dealloc
{
[super dealloc];
[_bar release]; // _bar is a member variable
}
And you expect to get a segmentation fault on the second line, but in practice you are not.
The reason for this is luck!
The OS will trap access to memory that your process does not own, but it doesn't police everything that happens inside your process. In this case, you are accessing memory that you have marked as free, but it still belongs to your process, and so behavior is undefined. The memory was valid a few milliseconds ago, and so it is likely that nobody has started reusing this page of memory yet, and so it probably still has valid data on it. So it might succeed. But it also might fail.
This is bad code and you shouldn't ship it. But just because it is incorrect and undefined doesn't mean it won't work.
-dealloc ultimately frees the memory associated with an Objective-C object (presumably through free(), but that's an implementation detail.) The only reason you are able to send a message after -dealloc is because of undefined behaviour. After [super dealloc] is sent, any further messages to self or its ivars is unsafe.
In the simplest "conceptual" case, the dealloc routine for NSObject does the free operation, mirroring the malloc done in the alloc routine. In practice it may be different, but that's all smoke and mirrors, so long as the conceptual model is satisfied.
If you put [super dealloc] first in your (pre-ARC) dealloc routine it mostly doesn't seg fault because the space, while freed, has not had time to be overwritten by some other object (and it doesn't physically go away when deallocated -- it just goes into an "available" list).
Yes, alloc is where the allocation is done. Note that it may or may not be done, sometimes there's no allocation at all (this is an implementation detail). The allocation generally happens in the NSObject implementation of alloc.
If memory was allocated, then the chained call to dealloc is the one that eventually releases it.
You are not supposed to access instance variables after calling [super dealloc]. This does not mean that if you do you get a segfault. You may or may not segfault, it's undefined behavior.
An important thing to remember, however, is that you should never call dealloc directly, except for the call to [super dealloc] in the dealloc implementation itself. Objective C is reference counted. When you are done with an object you do not dealloc it. Instead you release it (or autorelease it if you are done but you are returning it to the caller and have no idea if the caller will use it or not). The actual call to dealloc happens automatically when the system is sure that nobody is going to reference that object any more.
Edit:
I shall clarify sometimes there's no allocation at all. In fact the allocation generally happen if you call alloc, but the init* methods may undo it. As a rule all calls to alloc should immediately be followed by a call to one of the initializers. The initializers, however, do not need to initialize the self they receive. They could instead get rid of it (therefore freeing the memory) and return a completely different object, which may or may not be allocated.
Therefore, in that case, the memory allocated by alloc is in fact released by the initializer (may or may not call dealloc to do that). ANd the object that you get after initialization may be a static object that is not allocated on the heap and will never be freed. It could also be a non pointer (an invalid address) that is cast to (void*) (aka id) and returned.
I have a basic question here.
I know that dealloc will be called when the object's reference count becomes zero,and dealloc releases all the resources hold by the object or frees memory, right?
The object reference count becomes zero if we send release message to that object right?.
Lets consider the following object with its property created as,
#property (retain) NSString* myString;//reference count 1
and dealloc
[myString release];//reference count 0
[super dealloc];
I am not releasing the myString object any where except in dealloc.
My question is who is making myString object reference count to zero so that dealloc will be called?
Please clarify my doubt.
Anything that maintains ownership of the object is responsible for releasing it. For example if the code you posted is the only thing that maintains ownership of the NSString stored in myString then when you call release the reference count will be decreased and the object will likely be deallocated (String literals are different). Now if you passed myString around or something else requested myString and retains it then that code is also responsible for releasing it which may be before or after you release it in the dealloc method.
I recommend referring to the documentation for reinforcing this concept.
Let's say your property myString is within your class MyClass. Each instance of your class is created and (presumably!) released. When that instance is [released], your dealloc method of MyClass is called. Your dealloc in turn calls release on your properties, which in turn invokes their dealloc, and so on until you reach the 'bottom' of this stack of objects using objects.
Your object will only be free'ed if the retain/release pairs match up. If you follow the cocoa memory management (see apple docs - advances memory management programming guide)
rules, you are the only 'owner' at that point - and running dealloc zap's the last reference away - free'ing the object.
Is it good practice for an object in Objective-C to commit suicide? That is, for an object to declare [self dealloc] where -dealloc permits an orderly wind down as usual? What are the principal risks?
As it happens I have a specific example, a custom timer object that extends NSObject and comprises an NSTimer instance and an NSUInteger which is set to limit the number of times the timer fires. When time is up the object tells the timer to -invalidate and then commits suicide by calling its -dealloc method. As this is automatic we have no worries about having to track the object or crucially knowing when is the correct moment to deallocate it.
For a more detailed explanation see my post over here.
You shouldn't be calling -dealloc. Instead call [self release] so the reference count goes to 0 and let the system call -dealloc.
Is it good practice for an object in Objective-C to commit suicide? That is, for an object to declare [self dealloc] where -dealloc permits an orderly wind down as usual? What are the principal risks?
No.
The only time you should ever write a call to dealloc is to send dealloc to the super object in the dealloc method of one of your classes. No exceptions.
If you try to send dealloc to an object at any other time, you risk leaving other objects with dangling pointers. Don't do it.
Should you ever send release to self? That is a different matter, but you should still follow the Memory Management Rules. If you have sent retain to self, then at some point you will need to send release to self. There is one exception which is in init, if initialisation fails you have to release self and return nil (I guess you could claim that alloc has sent retain to self).