Memory management with arrays

  • I have an array that is an instance variable. I'm trying to add an
    object to it, and autorelease that object, so the next time this
    happens, I can remove all objects in the array and the object will be
    gone.

    - (void)foo {
    [array removeAllObjects];
    Bar *bar = [[Bar alloc] init];
    [array addObject:[bar autorelease];
    }

    This should remove all the objects, and add a new one. Basically, I
    want the old Bar instance gone, and the new one in the array. However,
    when I do this, I get an EXC_BAD_ACCESS when it tries to -
    removeAllObjects. What's the problem?
  • Hi Jacob,

    On 2008-02-10, at 14:18, Jacob Bandes-Storch wrote:

    > This should remove all the objects, and add a new one. Basically, I
    > want the old Bar instance gone, and the new one in the array.
    > However, when I do this, I get an EXC_BAD_ACCESS when it tries to -
    > removeAllObjects. What's the problem?

    Without seeing more code, I'd guess that you're not retaining the array.

    Jonathon Mah
    <me...>
  • I am retaining the array when I create it initially, and releasing it
    on dealloc.

    On Feb 9, 2008, at 10:10 PM, Jonathon Mah wrote:

    > Hi Jacob,
    >
    > On 2008-02-10, at 14:18, Jacob Bandes-Storch wrote:
    >
    >> This should remove all the objects, and add a new one. Basically, I
    >> want the old Bar instance gone, and the new one in the array.
    >> However, when I do this, I get an EXC_BAD_ACCESS when it tries to -
    >> removeAllObjects. What's the problem?
    >
    >
    > Without seeing more code, I'd guess that you're not retaining the
    > array.
    >
    >
    >
    > Jonathon Mah
    > <me...>
    >
  • Hi, Jacob,

    Maybe I'm missing something, but this "should work."  I suspect that
    the problem lies elsewhere in your code.  Can you give us (the list) a
    little more information on your file, such as relevant surrounding code?

    Also, apologies if this is a basic question, but is your array
    definitely declared and instantiated properly? and, additionally, is
    it an NSMutableArray, and not a standard NSArray?

    Cheers,
    Andrew

    On Feb 9, 2008, at 7:48 PM, Jacob Bandes-Storch wrote:

    > I have an array that is an instance variable. I'm trying to add an
    > object to it, and autorelease that object, so the next time this
    > happens, I can remove all objects in the array and the object will
    > be gone.
    >
    > - (void)foo {
    > [array removeAllObjects];
    > Bar *bar = [[Bar alloc] init];
    > [array addObject:[bar autorelease];
    > }
    >
    > This should remove all the objects, and add a new one. Basically, I
    > want the old Bar instance gone, and the new one in the array.
    > However, when I do this, I get an EXC_BAD_ACCESS when it tries to -
    > removeAllObjects. What's the problem?
  • Here is my guess, just because i hit this recently. It had to do with
    the [bar autorelease] call. This returns an autoreleased object. That
    may not be valid when you cam back around to removeAllObjects. Try the
    following:

    void foo
    {
    [array removeAllObjects];

    Bar* bar = [[Bar alloc] init];
    [array addObject:bar];
    [bar release];
    }

    the following should also work..

    void foo
    {
    [array removeAllObjects];

    Bar* bar = [[[Bar alloc] init] autorelease];

    [array addObject:bar];
    }

    Scott

    On Feb 9, 2008, at 7:48 PM, Jacob Bandes-Storch wrote:

    > I have an array that is an instance variable. I'm trying to add an
    > object to it, and autorelease that object, so the next time this
    > happens, I can remove all objects in the array and the object will
    > be gone.
    >
    > - (void)foo {
    > [array removeAllObjects];
    > Bar *bar = [[Bar alloc] init];
    > [array addObject:[bar autorelease];
    > }
    >
    > This should remove all the objects, and add a new one. Basically, I
    > want the old Bar instance gone, and the new one in the array.
    > However, when I do this, I get an EXC_BAD_ACCESS when it tries to -
    > removeAllObjects. What's the problem?
  • On Feb 9, 2008, at 10:16 PM, Scott Andrew wrote:
    > Here is my guess, just because i hit this recently. It had to do
    > with the [bar autorelease] call. This returns an autoreleased
    > object. That may not be valid when you cam back around to
    > removeAllObjects. Try the following:
    >
    > void foo
    > {
    > [array removeAllObjects];
    >
    > Bar* bar = [[Bar alloc] init];
    > [array addObject:bar];
    > [bar release];
    > }
    >
    > the following should also work..
    >
    > void foo
    > {
    > [array removeAllObjects];
    >
    > Bar* bar = [[[Bar alloc] init] autorelease];
    >
    > [array addObject:bar];

    The OP's code, as posted, was fine.  -autorelease returns the object
    being autoreleased and alloc returns an object that has been retained.

    Most likely, OP has overreleased one of the objects in the array.  Run
    with NSZombieEnabled to see what object is being overreleased.
    Better yet, turn on malloc stack logging (no compact) and use
    malloc_history to see allocation events at that address.

    b.bum
  • yay, one i THINK i can answer =)

    I thought NSArray already automatically retained all objects that were
    added to it?
    then once the array is released (dealloced?) the objects within are
    released as well
    so you may only need to just send it an auto released object

    so...

    void foo()
    {
    [array removeAllObjects];
    Bar *bar = [[Bar alloc] init];

    [array addObject:bar];
    }

    that should work fine, shouldn't it?

    please correct me if I'm wrong.

    regards

    Eric
  • On Feb 9, 2008, at 10:57 PM, ss2 cire wrote:
    > yay, one i THINK i can answer =)
    >
    > I thought NSArray already automatically retained all objects that
    > were added to it?
    > then once the array is released (dealloced?) the objects within are
    > released as well
    > so you may only need to just send it an auto released object
    >
    > so...
    >
    > void foo()
    > {
    > [array removeAllObjects];
    > Bar *bar = [[Bar alloc] init];
    >
    > [array addObject:bar];
    > }
    >
    >
    > that should work fine, shouldn't it?
    >
    > please correct me if I'm wrong.

    Double retain.

    [array removeAllObjects]; // leaks the doubly-retained bar

    b.bum
  • Oh, that's true....

    so change [array addObject:bar] to...

    [array addObject:[bar autorelease]];

    and that really should do it, but like others have said, there's
    probably something else going on
    with the code... is there anything more you can send us? maybe use a
    paste site to hold the code?

    regards,

    Eric

    On Feb 9, 2008, at 11:02 PM, Bill Bumgarner wrote:

    > On Feb 9, 2008, at 10:57 PM, ss2 cire wrote:
    >> yay, one i THINK i can answer =)
    >>
    >> I thought NSArray already automatically retained all objects that
    >> were added to it?
    >> then once the array is released (dealloced?) the objects within are
    >> released as well
    >> so you may only need to just send it an auto released object
    >>
    >> so...
    >>
    >> void foo()
    >> {
    >> [array removeAllObjects];
    >> Bar *bar = [[Bar alloc] init];
    >>
    >> [array addObject:bar];
    >> }
    >>
    >>
    >> that should work fine, shouldn't it?
    >>
    >> please correct me if I'm wrong.
    >
    > Double retain.
    >
    > [array removeAllObjects]; // leaks the doubly-retained bar
    >
    > b.bum
    >
  • True.. (late night). So basically. Put a break in bar's dealloc. See
    were the extra dealloc is cooming from.

    Scott

    On Feb 9, 2008, at 10:38 PM, Bill Bumgarner wrote:

    > On Feb 9, 2008, at 10:16 PM, Scott Andrew wrote:
    >> Here is my guess, just because i hit this recently. It had to do
    >> with the [bar autorelease] call. This returns an autoreleased
    >> object. That may not be valid when you cam back around to
    >> removeAllObjects. Try the following:
    >>
    >> void foo
    >> {
    >> [array removeAllObjects];
    >>
    >> Bar* bar = [[Bar alloc] init];
    >> [array addObject:bar];
    >> [bar release];
    >> }
    >>
    >> the following should also work..
    >>
    >> void foo
    >> {
    >> [array removeAllObjects];
    >>
    >> Bar* bar = [[[Bar alloc] init] autorelease];
    >>
    >> [array addObject:bar];
    >
    > The OP's code, as posted, was fine.  -autorelease returns the
    > object being autoreleased and alloc returns an object that has been
    > retained.
    >
    > Most likely, OP has overreleased one of the objects in the array.
    > Run with NSZombieEnabled to see what object is being overreleased.
    > Better yet, turn on malloc stack logging (no compact) and use
    > malloc_history to see allocation events at that address.
    >
    > b.bum
    >
  • On Feb 10, 2008, at 5:36 AM, Scott Andrew wrote:
    > True.. (late night). So basically. Put a break in bar's dealloc. See
    > were the extra dealloc is cooming from.
    >
    > Scott

    There won't be an "extra dealloc" -- once dealloc'd, the object is
    dead.  There is an extra -release coming first, but breaking on -
    release won't help, either as the object is dead by the time it happens.

    As I said, run the app with "-NSZombieEnabled YES".    This will cause
    a proxy to be dropped into memory in place of every dealloc'd object
    and said proxy will warn when messaged (because it should never be
    messaged).

    b.bum
  • I put some useful breakpoints on http://www.cocoadev.com/index.pl?NSZombieEnabled
    .  I found these scattered about the web and collected them onto the
    page.

    On Feb 10, 2008, at 11:39 AM, Bill Bumgarner wrote:

    > On Feb 10, 2008, at 5:36 AM, Scott Andrew wrote:
    >> True.. (late night). So basically. Put a break in bar's dealloc.
    >> See were the extra dealloc is cooming from.
    >>
    >> Scott
    >
    > There won't be an "extra dealloc" -- once dealloc'd, the object is
    > dead.  There is an extra -release coming first, but breaking on -
    > release won't help, either as the object is dead by the time it
    > happens.
    >
    > As I said, run the app with "-NSZombieEnabled YES".    This will
    > cause a proxy to be dropped into memory in place of every dealloc'd
    > object and said proxy will warn when messaged (because it should
    > never be messaged).
    >
    > b.bum
previous month february 2008 next month
MTWTFSS
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29    
Go to today
MindNode
MindNode offered a free license !