Nat! bio photo

Nat!

Senior Mull.

Twitter RSS

Github

Why NSNotifications during dealloc are a recipe for desaster

There was a Mulle internal discussion a year back about the use of dealloc notifications in some framework. Here is a little demo code that shows, that dealloc notifications - or notifications during dealloc in general - are not a good idea.

#import <Foundation/Foundation.h>
#import <Foundation/NSDebug.h>

@interface Problem : NSObject
{
}
@end


@implementation Problem

- (void) dealloc
{
   NSNotification  *notification;

   notification = [NSNotification notificationWithName:@"AsIDie"
                                                object:self];
   // it's synchronous... yet...
   [[NSNotificationCenter defaultCenter] postNotification:notification];
   [super dealloc];
}

@end


int main (int argc, const char *argv[])
{
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

   NSZombieEnabled = YES;
   [[[Problem alloc] init] release];
   [pool release];
   return( 0);  
}

This is the output:

2003-09-13 14:50:36.772 DeallocNotification[1679] *** *** Selector 'release' sent to dealloced instance 0x54450 of class Problem.
Break at '-[_NSZombie release]' to debug.
2003-09-13 14:50:36.784 DeallocNotification[1679] *** -[NSAutoreleasePool dealloc]: Exception ignored while releasing an object in an autorelease pool: NSGenericException *** Selector 'release' sent to dealloced instance 0x54450 of class Problem.
Break at '-[_NSZombie release]' to debug.

The problem is that NSNotification retains and subsequently autoreleases the object. The object is retained while in the process of deallocation. release and dealloc will be now called one more time from the NSAutoreleasePool, when it dies. But the deallocation can't be stopped now. This will lead to - possibly quite subtle - crashes.

Bottomline, keep the dealloc routine as stupid as possible to save yourself some trouble.


2 Comments

A photo of znek

From: znek

And yet there are cases where you don't have a chance to prevent sending notifications during dealloc. XRConnection's dealloc comes to mind, where you *have* to post an XRConnectionDidDieNotification. Interestingly, GNUstep (gnustep-base) now has a working solution for the problem mentioned above. Now guess what solved as a test case for this solution? ;-)

A photo of Nat!

From: Nat!

It would probably be better to overwrite -release like this:

- (void) release

{

if( [self retainCount] == 1)

{

//notify about to die

}

[super release];

}

The only problem is that the notification maybe sent to early or there may be duplicates, if someone doesn't cooperate.

Post a comment

All comments are held for moderation; basic HTML formatting accepted.

Name:
E-mail: (not published)
Website: