views:

39

answers:

3

I'm trying to get my head around memory management in Objective - C. I've used the garbage collector up until this point but before I go forward I'd like to get a better understanding of manually managing memory. I'm aware that I don't have an implementation of a dealloc method in this code.

My question is why does my inputString variable have a retain count of eleven here?

#import "AppController.h"


@implementation AppController

-(id) init
{
 [super init];
 NSLog(@"init");
 speechSynth = [[NSSpeechSynthesizer alloc] initWithVoice:nil];
 NSLog(@"speechSynth retain count is %d",[speechSynth retainCount]);
 return self;
}


-(IBAction) count:(id) sender
{
 NSString *outputString;
 int numberOfCharacters;

 inputString = [textField stringValue];
 numberOfCharacters = [inputString length];
 outputString = [NSString stringWithFormat:@"\"%@\" has %d characters",inputString,numberOfCharacters];

 [label setStringValue:outputString];
 [speechSynth startSpeakingString:outputString];
 NSLog(@"outputString retain count is : %i",[outputString retainCount]);
 NSLog(@"inputString retain count is: %d",[inputString retainCount]);
 NSLog(@"speechSynth retain count is: %d",[speechSynth retainCount]);
 [outputString release];
}
@end
+3  A: 

Apple's answer is "it doesn't matter." Track your references properly and let the runtime sort out the rest.

Internally, the runtime may be giving you a pointer to a singleton empty string (since NSStrings are immutable). Or it may be doing something else. But the reasoning behind a reference count for a variable that from your perspective has just been allocated is considered to be runtime internals, and you shouldn't rely on it for anything.

Use Instruments and zombie objects to figure out if you're leaking or over-releasing, and pretend that the retainCount message doesn't exist.

Seamus Campbell
By the way: outputString should not be released, since you haven't done a retain on it. And it looks like inputString, numberOfCharacters, and outputString should all be local variables, since you're not retaining them either explicitly with a call to retain, or implicitly by assigning them with a setter method ([self setInputString:...] or self.inputString = ...).
Seamus Campbell
Seriously, "just pretend `retainCount` doesn't exist" is the best advice you can get on the topic. `autorelease` would make the retain count useless to look at even if it weren't already.
Chuck
+1  A: 

What retain count do you think inputString should have? Bear in mind you got it from the Cocoa framework and who knows how many different objects inside it have references to it - 11 probably.

Look at the Memory Management Rules. They don't mention retain counts at all and that's for a very good reason: they are pretty much useless as a debugging tool.

JeremyP
A: 

From the Apple documentation:

Important: Typically there should be no reason to explicitly ask an object what its retain count is (see retainCount). The result is often misleading, as you may be unaware of what framework objects have retained an object in which you are interested. In debugging memory management issues, you should be concerned only with ensuring that your code adheres to the ownership rules.

Apple Documentation Thanks for the help everyone.

lampShade