Lefora Free Forum
login join
Loading
913 views

Help with memory management

Page 1
1–3
rookie - member
1 posts

I'm learning Objective C having come from assembler, C, and Python.

I've discovered a memory management weirdness:
   
Given a class Head, and a class Human defined elsewhere:

// 1) this leaves a permanent hanging retain count...
    human.head = [[Head alloc] init];
   
// 2) whereas this does not...
    Head *head = [[Head alloc] init];
    human.head = head;
    [head release];

// Will 1) ever get cleaned; i.e. is it assumed to autorelease at some point?

Many thanks - especially if this is a really stupid question.

?
288 posts


This is not a stupid question.  Memory in Management in Obj/C is a very serious (and boring) matter.
If you want to use autorelease, you'll have to provide a pool (and drain).  For example:NSAutoreleasePool* pool = [[NSAutoreleasePool alloc]init];
...
human.head = [[Head alloc]init];
...
[pool release];

I can only imagine the pool hooks the default alloc method of NSObject and thereby  knows about every allocated object.  pool release free's all the objects which have not been dealloc'ed while that pool was 'the active pool'.

If you do your own release (as you've done in 2), this is harmless because the pool knows the object has gone and doesn't free it again.

XCode 3/ObjC 2.0/Leopard introduced a garbage collector to spare you of this burden.

I've written the following code (and a command-line program with XCode 3.2.1) to try to demystify this.

I'll be honest, I'm rather puzzled by this.  If I comment off [brain release], it appears as though the [pool release] cleans memory without calling Head::dealloc - in other words it doesn't appear to have done anything with the dangling head!  (my guess is that [pool drain] calls [NSObject dealloc] for every object and not [Class dealloc].

Maybe another reader can enlighten us all.
 
#import <Foundation/Foundation.h>



@interface Head : NSObject {
}
@end
@implementation Head

- (id) init {
[super init] ;
NSLog(@"Head::init %@ retainCount = %d",self,[self retainCount]);
return self ;
}

- (void) release {
int count = [self retainCount] - 1 ;
NSLog(@"Head::release %@ retainCount after = %d",self,count);
[super release] ;
}

- (void) dealloc {
int count = [self retainCount] - 1 ;
[super dealloc] ;
NSLog(@"Head::dealloc %@ retainCount after = %d",self,count);
}

- (id) retain {
[super retain] ;
NSLog(@"Head::retain %@ retainCount = %d",self,[self retainCount]);
return self ;
}

@end

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

    // insert code here...
    NSLog(@"Hello, World!");
Head* head  = [[Head alloc]init] ;
Head* brain = [head retain];
NSLog(@"",head,brain);
[brain release];
[head  release];
    NSLog(@"Goodnight cruel world - let's pull the plug");

    [pool drain];

    NSLog(@"last word after draining the swamp");
    return 0;
}

__________________
?
63 posts

You add stuff to the pool using the autorelease command:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
Object *instance = [[[Object alloc]init]autorelease];
// …
[pool drain];

If the retainCount is not incremented, instance is released with the pool. Replace the comment with the following lines:
NSLog(@"Retain count = %i", [instance retainCount];
[myObject retain];

After the drain command, add these lines:

NSLog(@"Retain count = %i", [instance retainCount];
[myObject release];

__________________
kompilesoft

come and see my website! it's real cool reviews
Page 1
1–3

Locked Topic


You must be a member to post in this forum

Join Now!