Search code examples
objective-cdebuggingnullsigabrtnsmutableset

NSMutableSet count = 1, but that object is null?


Am using an NSMutableSet that is working great, up until this weird SIGABRT error popped up:

2011-07-05 17:01:00.249 Dama[1497:cd57] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFSet removeObject:]: attempt to remove nil'

ok, I can't remove nil, but here is my code:

    id item = nil;
if ([theSet count] == 0) { // This equals 1 !!
    item = [[[self getClass] alloc] init];
} else {
    item = [[theSet anyObject] retain]; //this returns nil !!
    [theSet removeObject:item]; // ERROR !!
}

Using gdb console, I found theSet looks like this:

(gdb) po theSet

{(

 (null)

)}

(gdb) print (int) [theSet count]

$1 = 1

How is this even possible?

P.S.: Am running in a multi-threaded environment .. I can't promise that the isn't being accessed by two threads at the same time, but it shouldn't be the case..

EDIT

Please, I really want to know how can the NSSet end up with (null), I dont care how it got there .. No matter how dirty my multi-threaded program is, This shouldn't happen, I think. [And I double checked, this set is only accessed by the background worker thread].

EDIT

2011-07-05 17:39:55.884 App[1608:c59f] Set count = 2 Contains: {(

< Step: 0xc43f3e0>,
< Step: 0x62f1800> )} 

2011-07-05 17:39:55.886 App[1608:c59f] Set count = 9 Contains: {(

>     < Step: 0x62eece0>,
>     < Step: 0xc490660>,
>     < Step: 0xcb597d0>,
>     < Step: 0x65a4f60>,
>     < Step: 0xc43f4b0>,
>     < Step: 0xc43f3e0>,
>     < Step: 0x65c8f60>,
>     < Step: 0xc499230>,
>     (null) )} //null appeared?!

HINT!!

Check out the Step dealloc method (xD):

-(void)dealloc{
    if (![[PoolStep sharedPool] purgeFlag]) {
        [[PoolStep sharedPool] doneWithItem:self]; //put it in the object pool for reuse..
    } else {
        NSLog(@"=== STEP ====> [ %d ]", --_counter);
        [children release];
        [super dealloc];
    }
}

Another HINT!!

PoolStep is a singleton without @synchronize block in the sharedPool method, since it's accessed by one thread only. (and the performance is needed)


Solution

  • Have you tried wrapping it and any other code that uses theSet in a synchronized(theSet) block, a threading issue could explain your issue. Maybe the null is caused by some intermediate state.