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.
Related
I have created an object using alloc/init method, and after I release it -dealloc should be called immediately as per documentation. I set a breakpoint on -dealloc method but it isn't hit, and my -dealloc method is not called.
Please tell me what is the reason behind that, and what is use of dealloc method in objective c ?
The -dealloc method is not always called when you expect it to be called. The runtime might also have issued a -retain on your object for internal reasons.
It's also possible that you have (directly or indirectly) caused an extra -retain to be issued. If the retains/allocs and releases are not balanced, you'll never see -dealloc called. It helps to turn on the Static Analyzer, to make sure your calls balance.
Just follow the memory management rules, don't second guess the runtime, and let the memory management system do its job.
The answers to When does dealloc method call? may help you understand what you're seeing.
because it still has reference. that means its reference count not reached to zero. i don't know your code, where it is referencing. but it is not calling that means somehow still it has reference. it may be because of strong relationship or parent-child relationship
all Objective-C objects are allocated on the heap, so they must
therefore be deallocated somewhere if you are not to run out of
resources.
This gave way to the reference counting method, which is still used
today: each object keeps count of any references held to it. If you
receive an object and you want to keep it, you retain that object,
incrementing its reference count. When you are done with it, you
release it, which decrements its reference count. Once that count
reaches zero, it is inferred that no one is referencing the object and
it is automatically deallocated using the -dealloc method.
Additionally, an object could be told to “release at some point in the
(hopefully) near future” using autorelease pools. The idea is that
somewhere on the stack (typically at the start of a thread or while
responding to input events) an autorelease pool is created and pushed
onto a stack. Any object can then be sent an -autorelease message, and
it is assigned to that pool.
When the pool object is deallocated, it simply sends a -release
message to all its assigned objects. That way, any objects that are no
longer used (i.e. they haven’t been explicitly retained) are then
deallocated.
The dealloc is called (at more cases) whenever your object is released. You can't directly call this method.
#interface myViewController:UIViewController
{
NSString *myStr;
}
#end
Here the dealloc method in the #implementation of myViewController will be called (at most cases) when the myViewController object is released, not when myStr is released.
Although you don't have to use if you ARC.
Can someone tell me what would actually happen if you override the dealloc method in Objective-C? As in would it crash or would it just start leaking memory all over the place. I've been wondering what would happen and why it is necessary to prevent the programmer from using dealloc directly.
And in what case would you had to do something like this?
EDIT: Sorry guys for not being clear. I was mainly talking in terms or ARC type coding.
Overriding -dealloc is an extremely common thing to do in non-ARC code. In fact, you'd be hard-pressed to find a class that doesn't override it.
The key thing to remember, though, is that every single override of -dealloc always ends with a call to [super dealloc].
Of course, in ARC code, overriding -dealloc is far less common. And if you do override it, you don't call [super dealloc], because the compiler will insert that for you. But remember, this is only true under ARC.
Before ARC overriding the dealloc method was very common, you were releasing the ivars the deallocated instance owned. Now, with ARC, is less common, however, you may have to do it in some special cases, like when you de-register an instance from observing with NSNotificationCenter.
The rule you talk about was not to call dealloc directly (not override), that would have usually led to a crash since you were bypassing Cocoa's internal reference counting system.
Edit: Based on your edit, if you call [super dealloc] under ARC, you'll get a compile time error. And if there was no error, it would have probably lead to duplicating the dealloc call, which would have made your program crash.
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).
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.
Hi i want to know the difference between drain, release,dealloc and retain in Objective-C.
retain increase the reference count on an object
release decreases the reference on an object
drain is used in place of release on ONLY for NSAutoreleasePool objects due to some arcana related to the Objective C garbage collection
dealloc is called by the system once the retainCount of an object hits 0. It is where you clean up various things your object has (like a deconstructor or finalizer). You should NEVER call it directly, except for calling [super dealloc] at the end of your dealloc routines.
You really should just read through Apple's memory management documentation.