piotr_ch
piotr_ch

Reputation: 510

iOS NSMutable array release behaviour

I have a problem with NSMutableArray alloc and release. See below code:

NSMutableArray *enemiesToDeleteArray = [NSMutableArray arrayWithCapacity:5];
...
else if ([enemy isActive] && !CGRectIntersectsRect(fieldOfView, enemyRect))
        {
            [enemiesToDeleteArray addObject:enemy];
        }
...
 [enemiesToDeleteArray removeAllObjects];
 [enemiesToDeleteArray release];

Above code crashes in a run. With a symbolic debug break error 'objc_release' or 'malloc_break_error'. Below I added backtrace from the occurence of objc_release error:

* thread #1: tid = 0x1c03, 0x01e140a5 libobjc.A.dylib`objc_release + 21, stop reason = EXC_BAD_ACCESS (code=1, address=0xa0020010)
    frame #0: 0x01e140a5 libobjc.A.dylib`objc_release + 21
    frame #1: 0x01e14bd9 libobjc.A.dylib`(anonymous namespace)::AutoreleasePoolPage::pop(void*) + 555
    frame #2: 0x023c6468 CoreFoundation`_CFAutoreleasePoolPop + 24
    frame #3: 0x002effc1 QuartzCore`CA::AutoreleasePool::~AutoreleasePool() + 19
    frame #4: 0x002ff35f QuartzCore`CA::Display::DisplayLink::dispatch(unsigned long long, unsigned long long) + 251
    frame #5: 0x002ff75f QuartzCore`CA::Display::TimerDisplayLink::callback(__CFRunLoopTimer*, void*) + 161
    frame #6: 0x023e3376 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22
    frame #7: 0x023e2e06 CoreFoundation`__CFRunLoopDoTimer + 534
    frame #8: 0x023caa82 CoreFoundation`__CFRunLoopRun + 1810
    frame #9: 0x023c9f44 CoreFoundation`CFRunLoopRunSpecific + 276
    frame #10: 0x023c9e1b CoreFoundation`CFRunLoopRunInMode + 123
    frame #11: 0x0312b7e3 GraphicsServices`GSEventRunModal + 88
    frame #12: 0x0312b668 GraphicsServices`GSEventRun + 104
    frame #13: 0x009d0ffc UIKit`UIApplicationMain + 1211
    frame #14: 0x000c81f6 MyAPP`main(argc=1, argv=0xbffff36c) + 134 at main.m:14
    frame #15: 0x00001fa5 MyAPP`start + 53

and a backtrace from malloc_break_error:

MyAPP(18609,0xac98ea28) malloc: *** error for object 0x112dee40: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug

(lldb) bt
    * thread #1: tid = 0x1c03, 0x97be7815 libsystem_c.dylib`malloc_error_break, stop reason = breakpoint 1.1
        frame #0: 0x97be7815 libsystem_c.dylib`malloc_error_break
        frame #1: 0x97be8d51 libsystem_c.dylib`free + 346
        frame #2: 0x023c5ea4 CoreFoundation`-[__NSArrayM dealloc] + 276
        frame #3: 0x01e159ff libobjc.A.dylib`-[NSObject release] + 47
        frame #4: 0x01e140d5 libobjc.A.dylib`objc_release + 69
        frame #5: 0x01e14bd9 libobjc.A.dylib`(anonymous namespace)::AutoreleasePoolPage::pop(void*) + 555
        frame #6: 0x023c6468 CoreFoundation`_CFAutoreleasePoolPop + 24
        frame #7: 0x002effc1 QuartzCore`CA::AutoreleasePool::~AutoreleasePool() + 19
        frame #8: 0x002ff35f QuartzCore`CA::Display::DisplayLink::dispatch(unsigned long long, unsigned long long) + 251
        frame #9: 0x002ff75f QuartzCore`CA::Display::TimerDisplayLink::callback(__CFRunLoopTimer*, void*) + 161
        frame #10: 0x023e3376 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22
        frame #11: 0x023e2e06 CoreFoundation`__CFRunLoopDoTimer + 534
        frame #12: 0x023caa82 CoreFoundation`__CFRunLoopRun + 1810
        frame #13: 0x023c9f44 CoreFoundation`CFRunLoopRunSpecific + 276
        frame #14: 0x023c9e1b CoreFoundation`CFRunLoopRunInMode + 123
        frame #15: 0x0312b7e3 GraphicsServices`GSEventRunModal + 88
        frame #16: 0x0312b668 GraphicsServices`GSEventRun + 104
        frame #17: 0x009d0ffc UIKit`UIApplicationMain + 1211
        frame #18: 0x000c81f6 MyAPP`main(argc=1, argv=0xbffff36c) + 134 at main.m:14
        frame #19: 0x00001fa5 MyAPP`start + 53

Please explain me someone, what am I doing wrong?

Upvotes: 0

Views: 517

Answers (2)

CSolanaM
CSolanaM

Reputation: 3368

NSMutableArray *enemiesToDeleteArray = [NSMutableArray arrayWithCapacity:5]; returns an autoreleased instance, and that gets cleaned up some time after leaving the initializer. Now the pointer enemiesToDeleteArray points to undefined memory. You need to do:

enemiesToDeleteArray = [[NSMutableArray arrayWithCapacity:5] retain];

or

enemiesToDeleteArray = [[NSMutableArray alloc] initWithCapacity:5];

Upvotes: 2

bioffe
bioffe

Reputation: 6383

You should not release enemiesToDeleteArray at all. It will get autoreleased at the end of the current scope. You didn't use alloc at all, so this object is auto managed.

Upvotes: 4

Related Questions