Suicide: Objective-C objects calling their own -dealloc methods on themselves - objective-c

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).

Related

Dealloc method isn't called when i release perticular object

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.

Why can I release an ivar after [super dealloc] without segfaulting?

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.

performSelector: afterDelay: without retaining the target?

I've got a class which uses NSURLConnection to open a long-running connection to a server. When the connection's closed, either in connectionDidFinishLoading: or connection:didFailWithError:, I want to wait 15 seconds then retry the connection.
At the moment I'm using [self performSelector:#selector(restartConection) withObject:nil afterDelay:15.0];, but this leads to the undesired situation that when the object is released by its creator, the performSelector and NSURLConnections perpetually retain 'self', and it never gets deallocated.
How can I do this without perpetually retaining the object? Any help'd be much appreciated.
Thanks, -Alec
I think your only option is to send
[NSTimer cancelPreviousPerformRequestsWithTarget: object];
at some point, probably, before releasing the object. If the timer hasn't been scheduled, this is a no-op, but is not free performance-wise.
You cannot avoid retaining the object. It is retained in order to save you from ugly crashes when in the next main loop cycle the runtime is going to call your selector on the released object.
If you really insist on having your object released immediately without waiting for your delayed selector, I would suggest you to create a separate proxy class. Say your class is called A, create proxy class B which will have a weak reference to your class A (i.e. __weak A* a) and restartConnection selector which will check if the weak reference is valid. If so it would invoke restartConnection on your A object. Then, do, of course, a delayed selector on B's restartConnection
But first of all, I would really suggest that you reevaluate whether you really cannot live with the retain.

Retain count and dealloc in iPhone

I want to ask about the iPhone application and objective C question. In the implementation program, there are function called 'dealloc', does this function only be called one time by the application?
For example, if I alloc a object and retain it 2 times, the retains count is 2 and I never use 'release' in the program, unless in the dealloc. Will the object be removed from the memory, or the objective will be removed from the memory. Thank you.
In the implementation program, there are function called 'dealloc', does this function only be called one time by the application?
Yes. -dealloc destroys the object. Trying to send any message to it again, including -dealloc is an error.
if I alloc a object and retain it 2 times, the retains count is 2
Careful. The retain count is at least 3. Other things than your code might retain the object. It's better not to worry to much about retain counts and only think in terms of ownership.
Each alloc, new, copy or retain is an claim of ownership. The object's dealloc method will only be called when all claims of ownership have been relinquished. A claim of ownership is relinquished by sending -release. So if you never release an object except in its own dealloc, you'll never release it.
dealloc is called once by the system when the object is destroyed (when its reference count reaches 0). If you have member variables in your class that you alloc in your init function, you must release them in your dealloc function.
If you give someone a pointer to one of those member objects and they retain it, the member could survive the release in your dealloc, but by sending a retain message they are taking responsibility for sending a release message later, ensuring its eventual destruction.

Objective-C Memory Management: When do I [release]?

I am still new to this Memory Management stuff (Garbage Collector took care of everything in Java), but as far as I understand if you allocate memory for an object then you have to release that memory back to the computer as soon as you are finished with your object.
myObject = [Object alloc];
and
[myObject release];
Right now I just have 3 parts in my Objective-C .m file: #Interface, #Implementation and main. I released my object at the end of the program next to these guys:
[pool drain];
return 0;
But what if this program were to be a lot more complicated, would it be okay to release myObject at the end of the program?
I guess a better question would be when do I release an object's allocated memory? How do I know where to place [myObject release];?
This is probably a little over-simplified, but in general, you are going to want to release it where you declared it.
If you declare an object INSIDE a particular method call, then by definition, you will be done with that object (or at least that handle to that object) at the end of that method call... release it then.
If you declare an object as an instance variable, then by definition you will be done with it when that instance is destroyed... release it in the dealloc method of that class.
Keep in mind that "release" does not equal "destroy." When passing objects around in your application, it may make sense to have more than one handle to that object stored in different places... in that case "release" means "I'm done with this object, but someone else may still be using it." Deallocation only occurs when the number of "handles" (retain count) reaches zero.
Apple has some fantastic documentation on memory management, I would check it out at developer.apple.com.
You essentially have three kinds of objects, each with a different pattern.
Transients Objects
In general, you should autorelease transient objects. These are objects that are allocated locally and do not need to exist beyond the method in which they are called. Or they are passed around from method to method.
Chain of Ownership
When one object exists as an instance field inside another, you should release the "owned" (or "child") object when the "owner" (or "parent") object goes out of existence. This is done in the dealloc method of the parent object:
- (void) dealloc {
[child release]; // child was declared as an instance variable
[super dealloc];
}
Lifetime of the Program
When an object is intended to exist for the lifetime of the program, it usually isn't necessary to call release at all, unless some kind of resource cleanup needs to occur. You can put this in applicationWillTerminate:, which you can look up in Apple's documentation.
(You should probably avoid having such objects, but that is a discussion for another question.)
You have to think in terms of ownership. When you take ownership of an object by calling alloc, new or retain, you're also responsible for releasing it, either by calling autorelease when you return an owned object to the caller, or by calling release.
A general rule is:
Local variable: release it within the same method. When you want to return it to the caller, use autorelease
Class member: release it in the dealloc method