views:

83

answers:

4

I have an object factory that hands out instances of a few "constant," immutable objects. I'd like these objects to be protected against bad memory management by clients. This is how I've overridden the class's key methods. Am I missing anything (code or other considerations)?

- (id)retain
{
    return self;
}

- (NSUInteger)retainCount
{
    return UINT_MAX;
}

- (void)release
{
    // nothing.
}

Update for later Drive-by question readers: This was (by intention) a special-case, double-black-diamond Cocoa question. If you're trying to create a regular singleton, see the answers below regarding shared instances, etc. This question (and the chosen answer) falls into the "you should be sure you know what you're doing" before choosing this implementation strategy.

+1  A: 

You may also want to override copyWithZone: and autorelease:

- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

- (id)autorelease
{
    return self;
}
mipadi
Overriding autorelease isn't really necessary if the object's `release` method is already a nop, but I suppose it may help keep the autorelease pool clean.
dreamlax
And overriding copyWithZone: to return self is a very bad idea unlerss the object is immutable.
JeremyP
+1  A: 

Hmmm, to really make it permanent:

- (void) dealloc
{
    return;
    [super dealloc]; // stop compiler warning
}

But, what advantage does this really have? Are your clients the kind that don't follow well-documented memory management rules?

dreamlax
I guess this depends on whether you prefer the "no call to super" warning or the "unreachable code" warning. :)
quixoto
@quixoto: With `-Wall -Wextra` you get the `missing [super dealloc]` warning but not an unreachable code warning.
dreamlax
interesting. thanks.
quixoto
+1  A: 

The idea of breaking the retain/release contract like that has a real bad smell to it. Would something like keeping a reference to the singleton objects in the class object be good enough? You would thereby prevent the object from being released in normal code.

If you are just protecting against an accidental over-release a better strategy would be to fail fast and get the original problem fixed, would it not? I just don't like the solution breaking things worse to accommodate broken code.

Ukko
+2  A: 

It sounds like you're trying to create a singleton. This is a very common pattern and there's been lots written about it. These links should tell you all you need to know:

http://www.mikeash.com/pyblog/friday-qa-2009-10-02-care-and-feeding-of-singletons.html

http://boredzo.org/blog/archives/2009-06-17/doing-it-wrong

And of course the Apple documentation here and here.

Rob Keniger
The counter-argument to my own, which I'm sure Kendall Helmstetter Gelner would raise if I weren't beating him to it right now ☺ , is that it's better to not crash (even if it means a bug exists latent) than to reveal a crashing bug through a user. It's a fair point, so it's up to every developer to decide for themselves whether they want war on bugs at the risk of potentially crashing on users, or to avoid crashing on users while allowing bugs to potentially exist.
Peter Hosey
Thanks for the discussion guys. I understand both the value of the standard singleton pattern in Cocoa and the perils (both immediate and delayed) of what I'm attempting. To Peter's (counter-arguing) point, I am--in this case--trying to prevent crashes in client code, for I do subscribe to the school of thought that would rather have zero crashes (and resulting data loss, as it happens) out in the field than pattern-perfect code. I'm doing this on my own recognizance. :)
quixoto
I was raised in the other school of thought that incorrect execution should be terminated. That does not mean a crash per se, it did when we used core files to sort things out. There is a strong case for writing code that can operate on less than perfect input for instance. But there is nothing worse than a program that destroys my data because somebody is ignoring exceptions.
Ukko
(I see your point, too, Ukko, but what if real data is being destroyed because someone is screwing up memory management by over-releasing singletons? That's what's happening here, so the judgement is relative.)
quixoto