0

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)

Mazyod
  • 22,319
  • 10
  • 92
  • 157

1 Answers1

2

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.

Nathan Day
  • 5,981
  • 2
  • 24
  • 40
  • Problem is am accessing this set (roughly) once every 2ms (on simulator) .. performance is my number one priority... – Mazyod Jul 05 '11 at 14:43
  • You should nevertheless try this in a debug build. After this experiment you will know whether or not your problem is deterministic or a threading issue. 2ms is enough time to take the lock. – Nikolai Ruhe Jul 05 '11 at 14:54
  • Problem is, it's random .. I just played the game for 10 minutes, nothing happened .. The question is: "How can NSSet Contain null?" – Mazyod Jul 05 '11 at 14:59
  • The answer is that NSMutableSet cannot contain null under normal circumstances. An exception is thrown if you try to add null. If it's a threading issue, you **have** to put some synchronization on. There's no way around it. – JeremyP Jul 05 '11 at 15:14
  • if only one thread accesses this set, what's the point of @sync block? – Mazyod Jul 05 '11 at 15:30