PDA

View Full Version : NSArray count error




Richard Birkett
Jan 14, 2012, 09:51 AM
Hello,
I have this code:

if ([variableFactors count] >= 1) {
short j = 0;
bool shouldRun = true;
while (shouldRun) {
if ([(RBMVariableFactor *)[variableFactors objectAtIndex:j] exponent] == 0) {
//if factor is empty then remove
[variableFactors removeObjectAtIndex:j];
}else{
j++;
}
shouldRun = (j <= ([variableFactors count] - 1));
}
}
When I have variableFactors with 1 object that satisfies the second if statement, it gets removed before the shouldRun line.
At this point I check with breakpoints that j is 0, variableFactors says '0 objects', I set a breakpoint for after shouldRun is reassigned and it is still true!!! The while loops again and the code crashes because I'm accessing an empty array.
Please help...

Richard



robvas
Jan 14, 2012, 10:24 AM
I'm getting a compile error on the line ([(RBMVariableFactor....

Your last line where you do 'shouldRun = ....' is the problem.

Look at this program:

NSMutableArray *variableFactors = [NSMutableArray arrayWithObjects:@"Foo", nil];

NSLog(@"Count is %lu", [variableFactors count]);
[variableFactors removeObjectAtIndex:0];

NSLog(@"Count is %lu after removing object at index 0", [variableFactors count]);

NSLog(@"Count - 1 is %lu", [variableFactors count] - 1);


It outputs:
MBHelp[1003:903] Count is 1
MBHelp[1003:903] Count is 0 after removing object at index 0
MBHelp[1003:903] Count - 1 is 18446744073709551615


The 'count' method returns an unsigned int - which can't be negative, which is probably what you were expecting to compare j to.

JoshDC
Jan 14, 2012, 10:37 AM
[NSArray count] returns an unsigned integer. Taking 1 from 0 will cause it to wrap around to its maximum value (NSUIntegerMax), so this:

NSLog(@"%d", 0 <= ([[NSArray array] count] - 1));


Will print 1, as it evaluates to 0 <= NSUIntegerMax.

You can either cast the value to a signed integer:

j <= (NSInteger)([[NSArray array] count] - 1)

Or use a different inequality:

j < [[NSArray array] count]

I'd suggest the second option.

As a side point, you'd usually see people checking for a non-zero count like this:

if ([variableFactors count] > 0)

Or more succinctly as:

if ([variableFactors count])

Richard Birkett
Jan 14, 2012, 10:57 AM
Thank you both so much, I removed the = and -1, now it works perfectly.
:)

gnasher729
Jan 14, 2012, 11:14 AM
Hello,
I have this code:

if ([variableFactors count] >= 1) {
short j = 0;
bool shouldRun = true;
while (shouldRun) {
if ([(RBMVariableFactor *)[variableFactors objectAtIndex:j] exponent] == 0) {
//if factor is empty then remove
[variableFactors removeObjectAtIndex:j];
}else{
j++;
}
shouldRun = (j <= ([variableFactors count] - 1));
}
}
When I have variableFactors with 1 object that satisfies the second if statement, it gets removed before the shouldRun line.
At this point I check with breakpoints that j is 0, variableFactors says '0 objects', I set a breakpoint for after shouldRun is reassigned and it is still true!!! The while loops again and the code crashes because I'm accessing an empty array.
Please help...

Richard

Just saying:

for (NSInteger j = [variableFactors count] - 1; j >= 0; --j)
if ([(RBMVariableFactor *)[variableFactors objectAtIndex:j] exponent] == 0)
[variableFactors removeObjectAtIndex:j];