A Memory Management question

Discussion in 'Mac Programming' started by GFLPraxis, Jun 24, 2010.

  1. GFLPraxis macrumors 604

    GFLPraxis

    Joined:
    Mar 17, 2004
    #1
    Hello,
    So, I originally started with a book, but have transitioned over to taking the Stanford CS 193p class on iTunes U, which has been a much better form of learning for me. I'm fairly early on in the class, but I had a question, and was wondering if I can get some assistance.


    Take this theoretical piece of code:

    Code:
    NSMutableArray *poly = [NSMutableArray alloc] init];
    PolygonShape *polygon1 = [[PolygonShape alloc] init];
    PolygonShape *polygon2 = [[PolygonShape alloc] init];
    PolygonShape *polygon3 = [[PolygonShape alloc] init];
    
    [poly addObject:polygon1];
    [poly addObject:polygon2];
    [poly addObject:polygon3];
    
    Followed by:
    Code:
    [polygon1 release];
    NSLog(@"test1");
    
    [polygon2 release];
    NSLog(@"test2");
    
    [polygon3 release];
    NSLog(@"test3");
    
    [poly release];
    NSLog(@"test4");
    

    With the note that PolygonShape has the following method, simplified:

    Code:
    - (void)dealloc
    {
    NSLog(@"dealloc ran");
    
    //release some integer ivars
    
    [super dealloc];
    
    }
    

    My Console results are:

    Code:
    test
    test2
    test3
    dealloc ran
    
    followed by an EXC_BAD_ACCESS crash.

    Why is dealloc only running when the array is released and not the objects I'm running it on? Isn't it my responsibility to individually release everything I ran alloc/init on in the local scope?

    Thanks for any clarification on how I'm looking at this. :)
     
  2. jared_kipe macrumors 68030

    jared_kipe

    Joined:
    Dec 8, 2003
    Location:
    Seattle
    #2
    Collection classes like NSArray, NSDictionary, and so on almost always retain the objects when you put them in.

    After adding an object to an array, the array "owns" the object as well.
     
  3. Catfish_Man macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #3
    The code you posted appears to be correct, so I suspect the code you're running has some subtle differences from what you posted.

    (Also the code you posted won't compile, it's missing a square bracket ;) )

    <edit>
    This response was only about the crash. The reason why -dealloc isn't running until then is as jared_kipe describes.
    </edit>
     
  4. Guiyon macrumors 6502a

    Joined:
    Mar 19, 2008
    Location:
    North Shore, MA
    #4
    I believe this may be your problem here. Integers are not objects, you don't release them. Are you sure you're not getting any compiler warnings? GCC should have been pretty pissed if you were trying to tell it to send a message to a non-object.
     
  5. GFLPraxis thread starter macrumors 604

    GFLPraxis

    Joined:
    Mar 17, 2004
    #5
    Aha! It was the combination of the two.

    I did get some compiler warnings, and Guiyon's post explains the crashing, but I was focusing on the memory management question before tackling the crash.

    I was trying to figure out why Dealloc wasn't being called until later; and jared_kipe hit the nail on the head. I didn't realize the array retained it. That explains why Dealloc was being called only after the array was released.

    Thanks much, all.
    So, I take it that this means that calling release on an array also makes it release everything it holds, correct?


    OK, so one last thing. The application completes fully, but the console logs the following error:

    Code:
    2010-06-24 22:18:04.499 WhatATool[2547:80f] *** __NSAutoreleaseNoPool(): Object 0x1050f0 of class NSCFString autoreleased with no pool in place - just leaking
    2010-06-24 22:18:04.507 WhatATool[2547:80f] *** -[NSAutoreleasePool drain]: This pool has already been released, do not drain it (double release).
    Anu thoughts on the meaning of his?
     
  6. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #6
    That's only true if the array is dealloc'ed as a result of your release. Just because you relinquish ownership of some object doesn't mean every other owner loses its ownership.

    Now, if you know that you are the sole owner of an object, and you release it, then in general, it's going to dealloc itself. For any object that has an owning reference to any other object, it will then release its owned objects. This is in accordance with the rules in the Memory Management Guide for writing dealloc's. Do you have any reason to think that NSArray wouldn't follow the same rules as every other class?


    The first message means exactly what it says. An object of the stated class was autoreleased with no pool in place. Coincidentally, the second message also means exactly what it says. It shows you the message, -[NSAutoreleasePool drain], and tells you why it's wrong.

    If you're looking for an explanation of why you're getting these messages, then you'll have to post your code.
     

Share This Page