Memory allocation for NSString?

I am new to Objective-C and I am a little curious how I should manage memory for the local NSString variables shown below and associated instance variables inside the class object. The code I have is working fine, but just curious about the best practice.

Edited to include full code, nothing special like I said, I'm just wondering if in this context I should be doing alloc / release on NSString objects.

// MAIN ------------------------------------------------------------------- **
#import <Foundation/Foundation.h>
#import "PlanetClass.h";

int main (int argc, const char * argv[]) {

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    NSString *planet_01_Geek;
    NSString *planet_02_Geek;

    // Create planets
    PlanetClass *newPlanet_01 = [[PlanetClass alloc] init];
    [newPlanet_01 setGeekName:@"StarWars"];
    PlanetClass *newPlanet_02 = [[PlanetClass alloc] init];
    [newPlanet_02 setGeekName:@"Dune"];

    // Query a planet
    planet_01_Geek = [newPlanet_01 geekName];
    planet_02_Geek = [newPlanet_02 geekName];

    // Print details
    NSLog(@"Planet Geek    = %@", planet_01_Geek);
    NSLog(@"Planet Geek    = %@", planet_02_Geek);

    // Clean up
    [newPlanet_01 release];
    [newPlanet_02 release];
    [pool drain];
    return 0;
}

      

..

// CLASS HEADER ----------------------------------------------------------- **
#import <Foundation/Foundation.h>

@interface PlanetClass : NSObject {
NSString *geekName;
}

- (NSString*) geekName;
- (void) setGeekName:(NSString*)gName;
@end
// ------------------------------------------------------------------------ **

      

..

// CLASS BODY ------------------------------------------------------------- **
#import "PlanetClass.h"

@implementation PlanetClass

- (NSString*)geekName {
    return geekName;
}
- (void)setGeekName:(NSString*)gName {
    geekName = gName;
}
@end
// ------------------------------------------------------------------------ **

      

+2


source to share


4 answers


Read the rules for memory management . 9 simple paragraphs that explain everything you need to know.

Since geekName does not start with "alloc" or "new", or contains "copy", it should return a string that you do not "own". This way you don't need to (and really shouldn't) release it, and you shouldn't keep a link to it either. You can return it from the method you are in, in which case the name of your method must not start with "alloc" or "new" or contain "copy" either.

If you want to keep it, you have to take it over by calling save, or because its NSString is better to copy. This can be automatic if you assign it to the copy / keep property.

In the code you posted, you made a mistake on your network device. Your setter should take a copy of the input parameter, for example:

- (void)setGeekName:(NSString*)gName {
    if ( geekName != gName ) {
        [geekName release];
        geekName = [gName copy];
}

      

Then you also need the dealloc routines that will give out the geekName:

- (void) dealloc
{
    [geekName release];
    [super dealloc];
}

      



Alternatively, you can use Objective C properties. Instead of displaying your interface:

- (NSString*) geekName;
- (void) setGeekName:(NSString*)gName;

      

Use property:

@property (nonatomic, copy) NSString* geekName;

      

And instead of your implementation of setters and getters, let the system synthesize them for you:

@synthesize geekName;

      

You still need the dealloc method for the free geekName.

+8


source


This will depend on how you created the property for "geekName". I would suggest that it just returns a reference to an existing member in the class rather than creating a copy? If so, you don't have to worry about releasing anything in the code you have there.



You only need to worry about freeing the "geekName" member in dealloc () for the class it is in.

+2


source


Variables are free. Local variables are allocated for you by the compiler; instance variables are allocated by the runtime as part of the instance.

The objects that you put pointers to variables are not free; you may need to release them. Whether you need to free an object or not, the rules .

0


source


Depending on how you use the two local variables, you might need some memory management.

As your code reads, you are setting local variables to the pointers returned by two class objects. If you've written the classes correctly newPlanet*

, then the string objects should be freed when the classes are dropped. If your two local variables try to use pointers you will have problems as the objects are no longer

Two possible amendments:

1. Directly save strings

Since local variables are assigned directly, you must explicitly store objects explicitly:

planet_01_Geek = [[newPlanet_01 geekName] copy];
planet_02_Geek = [[newPlanet_02 geekName] copy];

      

I am specifying a copy here because this is the preferred way of storing objects that can be changed, otherwise if the original changes change, the local variable will also change.

2. Use properties (preferably)

It would be my preferred method: retain

, copy

or assign

for the instance variables processed class.

Declare the properties correctly, for example:

@property (nonatomic, copy) NSString *planet_01_Geek;
@property (nonatomic, copy) NSString *planet_02_Geek;

      

Use @synthesize

in implementation.

Then use property syntax to highlight the variables.

self.planet_01_Geek = [newPlanet_01 geekName];
self.planet_02_Geek = [newPlanet_02 geekName];

      

This way, the correct memory management rules will be applied on assignment, and synthesized accessors will also take care of releasing any object that is currently assigned to local variables.

Edit - note as additional class details are shown

There setGeekName:

is a memory leak in your method . When you assign a new pointer to a local variable, you are not sending a release to the object that was there. The best way to do this (using retain

, not copy

just make it:

- (void)setGeekName:(NSString *)gName {
    [gName retain]; // Hold on to the object that is passed in.
    [geekname release]; // Let go of your current object.
    geekName = gName; // Now allocate the new object.
}

      

0


source







All Articles