Re: Is Apple's singleton sample code correct?
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