Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

zippyfly

macrumors regular
Original poster
Mar 22, 2008
141
0
Hi.

Say, I alloc/init a pointer to an object:

NSObject *newObject = [newObject alloc] init];

Now, we add it to an NSArray with addObject:

Now, we release the array.

[array release];

The retain count to newObject should be 1 right now (2 after adding to the array and 1 after array is released).

When I issue [newObject release] is the memory to the POINTER *newObject being reclaimed or both the pointer and the pointed-to object?

Relatedly, when array is released, does it just decrement the retain count or does it decrement the retain count (for newObject) AND also releases the pointed-to object, leaving the pointer (which then points to a memory location that isn't actually being used)?

Thanks.
 
Sorry, just wanted to append a related question and this might make it even clearer for me.

So I alloc/init the object.

Now I add it to the array.

Now, I RELEASE the object BEFORE I release the array.

The object is still around right?

So when I release the ARRAY, then all the memory should be properly cleaned right?

(I guess my question is, I should release all objects first, to ensure their retain counts are decremented to 1, BEFORE any release is issued to arrays holding them, correct? Not the other way around?)
 
You're releasing the object, not the pointer to it. If you want to ensure that you don't accidentally use an invalid pointer, you can set it to nil after releasing it for safety. The array will handle releasing its contents when it's deallocated (not when it's released), so the order doesn't matter.

allocate array - array retain count is 1
allocate object - object retain count is 1
add object to array - object retain count is 2
release object - object retain count is 1
release array - array retain count is 0
array's dealloc is called by its retain count reaching 0 - object retain count is 0
object's dealloc is called its retain count reaching 0
 
Just to add:
You will never "release" a pointer. A pointer is not an Object. 99.9% of the time, your pointers will be stack-local, so they will just go away when the stack-frame gets popped. No need to worry about them at all. .1% of the time or less you may, for some reason, have used malloc or one of its friends to get some memory for a pointer or 20. In this case, you would need to free this memory when you're done with it, but that is definitely a different mechanism than release.

-Lee
 
OK great; thanks guys. I was thinking the pointer and the final object are somehow "paired up" -- so if a pointer is treated as any variable, if I declare a pointer and object inside a loop, and the loop exits without me releasing the object, does that mean the object is orphaned in memory, while the pointer to it has gone out of scope and was popped off that stack frame?
 
Once you leave the block (function, loop, if, stand-alone, etc.) that a variable is declared in, it's gone. So you get the memory back for the variable, but if that was the only pointer storing the address of an object, you can't get to that object any more. If you're using garbage collection, you're fine... the last reference to that thing is gone, it will get reaped by the GC system. If you're using autorelease pools, or straight-up retain/release, and you didn't release/autorelease the Object, you're going to be leaking memory.

-Lee
 
How come this still works?

Code:
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	
	NSString *myString = [[NSString alloc] initWithString:@"abcdefg"];
	
	NSString *myPointer = myString;
	
	[myString release];
	
	NSLog(@"%@",myPointer);
	
	NSLog(@"%@",myString);
	
    [pool drain];
    return 0;
}

Is that because even though the memory is released, the physical RAM has not been overwritten and the pointer(s) still point to the address of the object data?

I tried releasing three times but still get the printout.

Code:
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	
	NSString *myString = [[NSString alloc] initWithString:@"abcdefg"];
	
	NSString *myPointer = myString;
	
	[myString release];

	[myString release];

	[myString release];
	
	myString = NULL;
	
	NSLog(@"%@",myPointer);
	
	NSLog(@"%@",myString);
	
    [pool drain];
    return 0;
}
 
OK - I have a brain wave (which I need to verify); is this because the initiWithString method actually allocates into the autorelease pool and thus any manual release is ignored?
 
Offhand I would suspect that's an oddity of NSString. Constant strings actually bypass retain/release entirely and aren't really "allocated". Try it with an NSMutableString instead.
 
Much weirdness:

Code:
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	
	NSMutableString *myString = [[NSMutableString alloc] initWithString:@"abcdefg"];
	
	NSMutableString *myPointer = myString;
	
	[myString release];
	
	NSLog(@"myPointer is %@",myPointer);
	
	NSLog(@"myPointer is %@",myPointer);
	
	NSLog(@"myString is %@",myString);
	
	NSLog(@"myString is %@",myString);
	
	[pool drain];
    return 0;
}

Code:
Running…
2009-09-17 11:48:36.033 TestApp[16101:a0f] myPointer is myPointer is 
2009-09-17 11:48:36.042 TestApp[16101:a0f] myPointer is <NSCFLocale: 0x10010cb00>
2009-09-17 11:48:36.042 TestApp[16101:a0f] myString is <NSCFLocale: 0x10010cb00>
2009-09-17 11:48:36.043 TestApp[16101:a0f] myString is <NSCFLocale: 0x10010cb00>

Debugger stopped.
Program exited with status value:0.

I guess the weirdness is expected.

(Commenting out the release makes this work as expected.)
 
What you're seeing there is that a different (cocoa-allocated) object is now in the memory your string was using. This is why nil-ing after releasing can be a good defensive measure.
 
Thanks. I think my head is fairly wrapped around this thing now, and if not then maybe just another couple more days of studying.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.