views:

357

answers:

3

Hi

I am very new to Objective-C and was reading through memory management. I was trying to play around a bit with the NSAutoreleasePool but somehow it wont release my object.

I have a class with a setter and getter which basically sets a NSString *name. After releasing the pool I tried to NSLog the object and it still works but I guess it should not?

@interface TestClass : NSObject
{
    NSString *name;
}

- (void) setName: (NSString *) string;
- (NSString *) name;


@end

@implementation TestClass   

- (void) setName: (NSString *) string
{
        name = string;
}  

- (NSString *) name
{
    return name;
}

@end

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

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

TestClass *var = [[TestClass alloc] init];

[var setName:@"Chris"];
[var autorelease];
[pool release];

// This should not be possible?
NSLog(@"%@",[var name]);


return 0;
}
A: 

Hi

Thanks for your quick answer... as far as I understood does drain more or less the same thing as release... it just does not destroy the pool.... but it does not work with drain either...

Chris
see reply from highlycaffeinated.
Anders K.
+5  A: 

When you release the pointer var, you're telling the OS that the memory it pointed to is available to be reallocated. The pointer still points to that memory, and until it gets reallocated it still contains the remains of your object. Once it gets reallocated, trying to call the name method will no longer work.

highlycaffeinated
David Gelhar
Agree. It's working purely by luck because the block of memory pointed at by var still contains the content of the object.
JeremyP
This answers the direct question but also note @Dirks answer about other problems
Mark
The NSZombieEnabled is a good thing for a beginner like me... It will crash when trying to access a deallocated object just like David said..thanks guys
Chris
+2  A: 

Your code has several problems. First, you do neither copy nor retain the string stored into the name instance variable. So, if the string is released by whoever stored it into the property, you are left with a dangling reference. You should do

- (void) setName: (NSString*) aName {
    if( name != aName ) {
        if( name ) [name release];
        name = [aName retain];    // or copy
    }
}

or use properties right from the start.

Also, if you keep object references in instance variables, you should provide a proper definition of the dealloc method:

- (void) dealloc {
    self.name = nil;
    [super dealloc];
}

Finally, just because an object has been deallocated, does not mean, that the memory of the former instance is invalidated. Your original program is most likely calling a method on a dangling reference (var), which happens to work by sheer luck here. (In particular, to (auto)release does not automatically set the reference to nil).

Dirk
You can safely send release to nil, so your test that name is not nil is unnecessary.
JeremyP
Thanks a lot for your answer... This was exactly what happened. After releasing the pool I tried to create a new object with TestClass *var1 = [TestClass new]; The NSLog for [var name] was NULL.... when I set the name for var1 [var1 setName=@"John"] I actually was able to access "John" by the old object "var".... so [var name] actually printed "John" ...If NSZombieEnabled is set to YES it crashes. Which is perfectLesson learned. Thanks!
Chris