views:

46

answers:

3

Hi all,

I get this message. The thing is, I want to be able to tell cocoa to just not send the notification if the object no longer exists. Is there a way to do that?

The broader picture: I'm sending requests to a server, but while that request is going on, maybe the user has done something to destroy the object expecting the request. When the response comes back, the object that requested it is no longer around, so I just want to have the notification center not handle the message.
Right now, I'm retaining the object when it requests a message, and releasing it when it receives the response. This way, I don't send messages to deallocated instances. But if it never gets the response, then it may not be freed, which leads to memory leaks. Hence my reasoning for trying to gracefully handle messages to deallocated instances.

Any ideas?

A: 

If the object no longer exists and you don't want it to crash on sending a message to garbage (that is, if you have a pointer to a deallocated object and you send that pointer a message, resulting in a nasty crash), if you want to avoid that, set your pointer to nil after you release it. This signifies you are done with the object. Sending messages to nil is perfectly acceptable, but sending messages to pointed-at-garbage is not.

[iVar release];
iVar = nil; // done with this reference.
jbrennan
That really won't work. If an object is deallocated, then you have to set every single reference to said object to `nil` which requires a level of knowledge of the object graph such that it becomes pointless to try and use such a solution.
bbum
@bbum: that's a bit unfair (assuming it was you who downvoted). He only has to make sure that the pointer used by whatever handles the response is nil, which probably comes down to implementing some sort of "unregistering" code.
JeremyP
@JeremyP: That's true, but jbrennan's answer did not explain that adequately at all. This answer seems to suggest that simply nulling out the reference you used to call `release` is sufficient, when in fact it requires setting *every* live reference to nil when the object is released. It might just be an accidental oversimplification, but I think this answer definitely gives the wrong impression.
Chuck
@bbum: Right, perhaps I left the wrong impression in my answer. My answer really only satisfies the occasion where a local pointer is pointing to a deallocated reference, and doesn't affect other references to the garbaged object.
jbrennan
+3  A: 

There is no "failing gracefully" when you message a deallocated object.

An allocated object is backed by a bit of memory allocated on the heap. It may have many references to that allocation; many pointers that contain the address of said allocation. When the object is deallocated, all those pointers are still pointing to it unless explicitly reset to some other value. And, of course, once de-allocated that bit o' memory can be re-allocated.

That is to say that, no, there is no magic -- no efficient magic anyway [see NSZombie] -- for turning all pointers to a particular object into something that magically eats all messages without error.

In other words, you need to architect your app such that objects that are no longer viable are really no longer viable across all layers of your app.

bbum
Thanks - I've taken this into account and removed the object from the notification loop before deallocation to avoid the error.
Shaun Budhram
A: 

As bbum says, you can't send messages to deallocated objects. It's simply invalid. There isn't even such a thing as a "deallocated object" — once an object is deallocated, it's just gone. It's not a thing anymore and doesn't exist anywhere. Its old bit pattern might remain, or an unrelated object might be put in its place, or absolute garbage — that's where the crashes come from, not some magical "deallocated object" handler.

The correct thing to do if you don't want an object to be sent notifications anymore is just to unregister it from receiving them.

Chuck