Task C Confusion Memory Management

I was reading Apple's documentation for memory management and came across something I just don't understand. Basically, I don’t understand why there is no need to store the instance variable through the "getter" method. I wrote this little program to see what happens. I thought there was going to be a wreck, but I obviously missed something.

//  main.m
//  Test
//


#import <Foundation/Foundation.h>
#import "Test.h"

int main(int argc, char *argv[])
{
    NSAutoreleasePool *p = [[NSAutoreleasePool alloc] init];

    //Initialize the test object
    Test *t = [[Test alloc] init];

    //Set the value to 5
    [t setMyNum:[NSNumber numberWithInt:5]];

    //Save a temp number that points to the original number
    NSNumber *tempNum = [t myNum];

    //release old number and retain new
    [t setMyNum:[NSNumber numberWithInt:7]];

    //Shouldn't this crash because tempNum is pointing to a deallocated NSNumber???
    NSLog(@"the number is %@",tempNum);

    [p drain];
    return 0;
}

      

Does tempNum point to a deallocated object?

All help is greatly appreciated.

EDIT

This is the code in getter and setter methods

#import "Test.h"


@implementation Test
- (void)setMyNum:(NSNumber *)newNum {
    [newNum retain];
    [myNum release];
    myNum = newNum;
}

-(NSNumber *)myNum {
    return myNum;
}
@end

      

As you can see, I am calling the release on the old object.

EDIT

It was suggested and I thought that the reason tempNum still exists is because it hasn't been auto-implemented from the pool yet. But even after moving the [drain pool] right before the NSLog message, does it fail ??? Weird.

+1


a source to share


3 answers


Since you are not explicitly freeing any objects, nothing is released until the autoresource pool is removed. Try to insert [p drain]

before the last call NSLog

. This should cause the NSLog call to fail.

Also, if you don't store NSNumber in your setMyNum: method, you will find that it will fire if you add [p drain]

tempNum before the assignment.

To clarify the original question, calling a getter method does not necessarily (and does not necessarily) mean that the caller wants to own (i.e. store) the variable. If so, this code will flow:



NSLog("Number is %@", [t myNum]);

      

Also, it looks like NSNumber has an optimization where, for small numbers, they cache NSNumber objects, keep an extra copy, and return that version. Therefore, for small constants, it [NSNumber numberWithInt: N]

will return an object with two reference counts (accessible via [theNumber retainCount]

). To see clearly what will happen, use a large constant in your program, NSNumber will keep the "fresh" object with reference number 1 (which will also be auto-implemented).

+5


a source


#import "Test.h"

@implementation Test 

- (void)setMyNum:(NSNumber *)newNum
{      
    [newNum retain];
    [myNum release]; 
    myNum = newNum;
}

-(NSNumber *)myNum 
{      
    return myNum; 
} 

@end  

      



Here in the setter method [myNum release]

that frees mynum, but then we give a new value to newnum again, hence from the getter method the temp number gets a number that was not freed before [p drain]

so there will be no crash.

+1


a source


#import "Test.h"

@implementation Test 

(void)setMyNum:(NSNumber *)newNum
{      

[newNum retain];
[myNum release]; 
myNum = newNum;

}

(NSNumber *)myNum 
{      

return myNum; 

} 

@end  

      

Here is a setter method [myNum release];

that frees myNum

, but then we give a new value again newNum

, so from the getter method, the temp number gets a number that hasn't been freed before [p drain];

, so there won't be any crash. Even if the following code does not fail, as there is an autodetect pool, but no autodetect method.

[t setMyNum:[NSNumber numberWithInt:70]];

      

Thus, freeing the pool will not free the number.

0


a source







All Articles