views:

59

answers:

2

This is an object I made to do some flash cards. The first method (I left out the main part) generates a NSMutabaleArray of Card objects with the passed in operator and works fine. The second method, "drawFromDeck" gets called on a Deck object from my view controller and also works fine, but the Static Analyzer says I may be leaking an object.

Here is the code.

#import "Deck.h"

@class Deck;
@implementation Deck

@synthesize cards;

- (id)initDeckWithOperator: (NSString*)mathOper {

...

 return self;
}

- (id)drawFromDeck {
    int index = random() % [cards count];
    Card* selectedCard = [[cards objectAtIndex:index] retain];
    [cards removeObjectAtIndex:index];
    return selectedCard;
}

@end
+4  A: 

Yes you're leaking an object. You should

return [selectedCard autorelease];

The reason being you've -retained the selectedCard, so you've got the responsibility to -release it. But you can't use -release since it must be valid after the function ends, so you need to use -autorelease to transfer the ownership to the auto-release pool.

Of course, methods calling -drawFromDeck shouldn't -release its return value.

KennyTM
I'd say it would be clearer to just not retain the card in the first place. He has no reason to take ownership at that point. Card* selectedCard = [cards objectAtIndex:index];
Joshua Weinberg
@Joshua Weinberg - However, if he did that it may be deallocated at the instant -removeObjectAtIndex: was called. By using autorelease, at least it will exist long enough to be returned from the method.
Brad Larson
tested my assumption, I was wrong. Makes sense now that I think about it.
Joshua Weinberg
A: 

Thanks for the input. I didn't used to have the retain in there, but I would end up crashing for index being out of bounds of the array. I tried doing the autorelease thing, but I would crash then too - but like you said, I don't want to release that selectedCard because I need to use it when it gets back to my ViewController. I don't recall if I release it when I'm done with it in the ViewController, but would that work? Would the SA know that even though I return an object with a +1 retain count, that it gets released in the ViewController?

Steve
@Steve: You need to name the method like `-copy...` or `-new...`. And this is *bad* API design (BTW, you can comment in your own question).
KennyTM
Would you mind being more explicit? This is for me still pretty advanced - I grew up programming in basic on my Apple II+! I don't see how changing the name of the method would matter, but I'm probably not understanding what you mean.
Steve
The static analyzer uses method names as a cue for how the method operates. Read the Objective-C memory guidelines.http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
Joshua Weinberg
Thanks for the link! I changed the name from drawFromDeck to newCardFromDeck and kept the retain and the SA now thinks things are fine. No crashes and no apparent memory leaks. The question now is: Does the fact that the SA doesn't see a memory leak mean that there really isn't one?
Steve