• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Is Apple's singleton sample code correct?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Is Apple's singleton sample code correct?


  • Subject: Re: Is Apple's singleton sample code correct?
  • From: Shawn Erickson <email@hidden>
  • Date: Sat, 26 Nov 2005 07:38:43 -0800


On Nov 26, 2005, at 7:21 AM, David Gimeno Gost wrote:

But you don't need to override the methods to accomplish that. What
I'm saying is that the default (inherited) methods already do the
right job if users of the class follow the Cocoa's memory
management rules.

This is not the case. If you didn't override release, then (following Cocoa's memory management rules):

MyGizmoClass *gizmo = [[MyGizmoClass alloc] init];
// do some stuff
[gizmo release];

// do some more stuff

MyGizmoClass *gizmo2 = [[MyGizmoClass alloc] init];
[gizmo2 doSomething];  // crash

At this point, sharedGizmoManager is a pointer to a freed object.

Not if +allocWithZone: is written as I later suggested in the same e-mail you are responding to here. Note the added -retain message sent to the shared instance if it already exists:


+ (id) allocWithZone: (NSZone*) zone
{
    @synchronized( self ) {
        if ( sharedGizmoManager == nil ) {
            sharedGizmoManager = [super allocWithZone: zone];
        } else {
            [sharedGizmoManager retain];
        }
    }
    return sharedGizmoManager;
}

No Mmalcolm is correct, he is pointing out a flaw in the code you outline above. Looking at his example...


MyGizmoClass *gizmo = [[MyGizmoClass alloc] init];

The above (assuming it is the first call to alloc in the program) runs thru the "== nil" branch and triggers the allocation of the singleton which gets stashed in sharedGizmoManager and returned to the caller. The caller following the memory contract assumes he must later release the object (since he called alloc) so...


// do some stuff
[gizmo release];

The above sends a release to the singleton which in this case is balancing the implicit retain coming from [super allocWithZone:zone]. This will get your singletons dealloc method called and your objects memory deallocated since it reduces the retain count to zero. At this point then sharedGizmoManager is now pointing to a spot in memory that used to hold your singleton instance.


MyGizmoClass *gizmo2 = [[MyGizmoClass alloc] init];
[gizmo2 doSomething];  // crash

This is a second call to alloc which since sharedGizmoManager is non- nil will go thru the "!= nil" branch. This branch sends a retain to what used to be your singleton... which could be a different object now in the same spot in memory or nothing (could have a semblance of your singleton to sitting around) since the memory was freed.


So either the retain in your allocWithZone will cause a crash (will if using NSZombie for debugging) or the application will keep running and the caller will likely crash later on. More often then not with some exception about some random class doesn't support a singleton method.

-Shawn



_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


References: 
 >Re: Is Apple's singleton sample code correct? (From: David Gimeno Gost <email@hidden>)

  • Prev by Date: Re: Is Apple's singleton sample code correct?
  • Next by Date: Re: Is Apple's singleton sample code correct?
  • Previous by thread: Re: Is Apple's singleton sample code correct?
  • Next by thread: Re: Is Apple's singleton sample code correct?
  • Index(es):
    • Date
    • Thread