Search code examples
objective-cmemoryautomatic-ref-countingstack-overflowexc-bad-access

EXC_BAD_ACCESS error in Objective-C app - stack overflow?


In my Objective-C app I am receiving a EXC_BAD_ACCESS error (code = 2) in building a wordsearch app, and am using ARC in my project - but I cannot resolve the issue - could this be due to a stack overflow at all?

The code below refers to a wordsearch testing algorithm - it scans through each word with random coordinates to test if it will fit in a given direction. If it cannot, it picks another random coordinate point and tries again. After an amount of attempts if it can't fit the word in it scans through each co-ordinate point in order for a fit. If that doesn't work - I take out the wordsearch and start again from scratch.

This code works, up to a point. If the algorithm finds a valid wordsearch within around 1,000 attempts then it will proceed as expected. After around 1,000 (it differs each time) - it crashes with EXC_BAD_ACCESS. I tested for leaks and zombies without success.

The stack trace and error message is this (the offending line is not always the same...)

And the code is (this looks long but is actually just an if statement for 8 possible events and is coded similarly throughout):

This method looks to see if a word will fit in a grid based on its coordinates and direction:

- (void)checkWordToSearch:(NSString *)word rvalueToPick:(int)rvalue svalueToPick:(int)svalue
{
BOOL picked = FALSE;
BOOL isthereaconflict = FALSE;
NSString *theWord = word;
int r = rvalue;
int s = svalue;

for (int i = 0; i < [self.randomDirectionArray count]; i++)
{
    {
        if (picked == FALSE)
        {
            if ([[self.randomDirectionArray objectAtIndex:i]isEqualToString:@"1"]&&isthereaconflict == FALSE)
            {
                if ((r+1)>=[theWord length])
                {
                  //  NSLog(@"-1-");
                    for (int z = 0; z < [theWord length]; z++)
                    {
                        if ([[[self.arrayOfArrays objectAtIndex:r-z]objectAtIndex:s]isEqualToString:@""] || [[[self.arrayOfArrays objectAtIndex:r-z]objectAtIndex:s]isEqualToString:@"-"]||[[[self.arrayOfArrays objectAtIndex:r-z]objectAtIndex:s]isEqualToString:[theWord substringWithRange:NSMakeRange(z,1)]])
                        {
                        }
                        else {
                            isthereaconflict = TRUE;
                        }
                    }
                    if (isthereaconflict == FALSE)
                    {
                        _direction = 1;
                        _correctr = r;
                        _verticals++;
                        _corrects = s;
                        picked = TRUE;
                        _numberOfTries = 0;

                        if (_emergencyStart == TRUE)
                        {
                            _emergencyEnd = TRUE;
                        }
                    }

                }
                else
                {

                }
            }
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// GOING DOWN
            else if ([[self.randomDirectionArray objectAtIndex:i]isEqualToString:@"5"]&&isthereaconflict == FALSE)
            {
                if ((r+[theWord length])<=11)
                {
                    for (int z = 0; z < [theWord length]; z++)
                    {
                        if ([[[self.arrayOfArrays objectAtIndex:r+z]objectAtIndex:s]isEqualToString:@""] || [[[self.arrayOfArrays objectAtIndex:r+z]objectAtIndex:s]isEqualToString:@"-"]||[[[self.arrayOfArrays objectAtIndex:r+z]objectAtIndex:s]isEqualToString:[theWord substringWithRange:NSMakeRange(z,1)]])
                        {
                        }
                        else {
                            isthereaconflict = TRUE;
                        }

                    }

                    if (isthereaconflict == FALSE)
                    {
                        _direction = 5;
                        _verticals++;
                        _correctr = r;
                        _corrects = s;
                        picked = TRUE;
                        _numberOfTries = 0;
                        if (_emergencyStart ==TRUE)
                        {
                            _emergencyEnd = TRUE;
                        }
                    }

                }
                else
                {

                }
            }
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// GOING RIGHT
            else if ([[self.randomDirectionArray objectAtIndex:i]isEqualToString:@"3"]&&isthereaconflict == FALSE)
            {
                if ((s+[theWord length])<=11)
                {
                    for (int z = 0; z < [theWord length]; z++)
                    {

                        if ([[[self.arrayOfArrays objectAtIndex:r]objectAtIndex:s+z]isEqualToString:@""] ||[[[self.arrayOfArrays objectAtIndex:r]objectAtIndex:s+z]isEqualToString:@"-"]|| [[[self.arrayOfArrays objectAtIndex:r]objectAtIndex:s+z]isEqualToString:[theWord substringWithRange:NSMakeRange(z,1)]])
                        {
                        }
                        else {
                            isthereaconflict = TRUE;
                        }

                    }
                    if (isthereaconflict == FALSE)
                    {
                       // NSLog(@"Correct 3");
                        _direction = 3;
                        _horizontals++;
                        _correctr = r;
                        _corrects = s;
                        _numberOfTries = 0;
                        picked = TRUE;
                        if (_emergencyStart ==TRUE)
                        {
                            _emergencyEnd = TRUE;
                        }
                    }
                }
                else
                {

                }
            }
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// GOING LEFT
            else if ([[self.randomDirectionArray objectAtIndex:i]isEqualToString:@"7"]&&isthereaconflict == FALSE)
            {
                if ((s-1)>=0 && (s-1)>=[theWord length])
                {
                    for (int z = 0; z < [theWord length]; z++)
                    {
                        if ([[[self.arrayOfArrays objectAtIndex:r]objectAtIndex:s-z]isEqualToString:@""] ||[[[self.arrayOfArrays objectAtIndex:r]objectAtIndex:s-z]isEqualToString:@"-"]|| [[[self.arrayOfArrays objectAtIndex:r]objectAtIndex:s-z]isEqualToString:[theWord substringWithRange:NSMakeRange(z,1)]])
                        {
                        }
                        else {
                            isthereaconflict = TRUE;
                        }

                    }
                    if (isthereaconflict == FALSE)
                    {
                        _direction = 7;
                        _horizontals++;
                        _correctr = r;
                        _corrects = s;
                        _numberOfTries = 0;
                        picked = TRUE;
                        if (_emergencyStart ==TRUE)
                        {
                            _emergencyEnd = TRUE;
                        }
                    }
                }
                else
                {

                }
            }
            else if ([[self.randomDirectionArray objectAtIndex:i]isEqualToString:@"2"]&&isthereaconflict == FALSE)
            {
                //NSLog(@"GOING RIGHT UP");
                if ((r+1)>=[theWord length] && (s+[theWord length])<=11)
                {
                    for (int z = 0; z < [theWord length]; z++)
                    {
                        if ([[[self.arrayOfArrays objectAtIndex:r-z]objectAtIndex:s+z]isEqualToString:@""] ||[[[self.arrayOfArrays objectAtIndex:r-z]objectAtIndex:s+z]isEqualToString:@"-"]|| [[[self.arrayOfArrays objectAtIndex:r-z]objectAtIndex:s+z]isEqualToString:[theWord substringWithRange:NSMakeRange(z,1)]])
                        {
                        }
                        else {
                            isthereaconflict = TRUE;
                        }

                    }
                    if (isthereaconflict == FALSE)
                    {
                        _direction = 2;
                        _backdiagonals++;
                        _correctr = r;
                        _corrects = s;
                        picked = TRUE;
                        _numberOfTries = 0;
                        if (_emergencyStart ==TRUE)
                        {
                            _emergencyEnd = TRUE;
                        }
                    }
                }
                else
                {

                }
            }
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// GOING LEFT AND UP
            else if ([[self.randomDirectionArray objectAtIndex:i]isEqualToString:@"8"]&&isthereaconflict == FALSE)
            {
                if ((r+1)>=[theWord length] && (s-1)>=[theWord length] && (s-1)>=0)
                {
                    for (int z = 0; z < [theWord length]; z++)
                    {
                        if ([[[self.arrayOfArrays objectAtIndex:r-z]objectAtIndex:s-z]isEqualToString:@""] ||[[[self.arrayOfArrays objectAtIndex:r-z]objectAtIndex:s-z]isEqualToString:@"-"]|| [[[self.arrayOfArrays objectAtIndex:r-z]objectAtIndex:s-z]isEqualToString:[theWord substringWithRange:NSMakeRange(z,1)]])
                        {
                        }
                        else {
                            isthereaconflict = TRUE;
                        }

                    }
                    if (isthereaconflict == FALSE)
                    {
                        _direction = 8;
                        _diagonals++;
                        _correctr = r;
                        _corrects = s;
                        picked = TRUE;
                        _numberOfTries = 0;
                        if (_emergencyStart ==TRUE)
                        {
                            _emergencyEnd = TRUE;
                        }
                    }
                }
                else
                {

                }
            }
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// GOING RIGHT AND DOWN
            else if ([[self.randomDirectionArray objectAtIndex:i]isEqualToString:@"4"]&&isthereaconflict == FALSE)
            {
                if ((s+[theWord length])<=11 && (r+[theWord length])<=11)
                {
                    for (int z = 0; z < [theWord length]; z++)
                    {
                        if ([[[self.arrayOfArrays objectAtIndex:r+z]objectAtIndex:s+z]isEqualToString:@""] ||[[[self.arrayOfArrays objectAtIndex:r+z]objectAtIndex:s+z]isEqualToString:@"-"]|| [[[self.arrayOfArrays objectAtIndex:r+z]objectAtIndex:s+z]isEqualToString:[theWord substringWithRange:NSMakeRange(z,1)]])
                        {
                        }
                        else {
                            isthereaconflict = TRUE;
                        }

                    }
                    if (isthereaconflict == FALSE)
                    {
                        _direction = 4;
                        _diagonals++;
                        _correctr = r;
                        _corrects = s;
                        picked = TRUE;
                        _numberOfTries = 0;
                        if (_emergencyStart ==TRUE)
                        {
                            _emergencyEnd = TRUE;
                        }
                    }
                }
                else
                {

                }
            }
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// GOING LEFT AND DOWN
            else if ([[self.randomDirectionArray objectAtIndex:i]isEqualToString:@"6"]&&isthereaconflict == FALSE)
            {
                if ((s-1)>=[theWord length] && (r+[theWord length])<=11&&(s-1)>=0)
                {
                    for (int z = 0; z < [theWord length]; z++)
                    {
                        //NSString *theString = [theWord substringWithRange:NSMakeRange(z,1)];
                        if ([[[self.arrayOfArrays objectAtIndex:r+z]objectAtIndex:s-z]isEqualToString:@""] || [[[self.arrayOfArrays objectAtIndex:r+z]objectAtIndex:s-z]isEqualToString:@"-"]||[[[self.arrayOfArrays objectAtIndex:r+z]objectAtIndex:s-z]isEqualToString:[theWord substringWithRange:NSMakeRange(z,1)]])
                        {
                        }
                        else {
                            isthereaconflict = TRUE;
                        }

                    }
                    if (isthereaconflict == FALSE)
                    {
                        _backdiagonals++;
                        _direction = 6;
                        _correctr = r;
                        _corrects = s;
                        _numberOfTries = 0;
                        picked = TRUE;
                        if (_emergencyStart ==TRUE)
                        {
                            _emergencyEnd = TRUE;
                        }
                    }
                }
                else
                {

                }
            }
        }
    }

}

if (picked == FALSE)
{
    _numberOfTries ++;

    if (_numberOfTries > 500 && _emergencyStart == FALSE)
    {
        _problemSorted = FALSE;
        [self emergencyCheck:theWord];
    }

    else if (_emergencyStart == TRUE)
    {

    }

    else
    {
      [self gameWithWord:theWord];
    }

}

else{
    //NSLog(@"NO CONFLICT");

    if (_emergencyEnd == TRUE)
    {
         _problemSorted = TRUE;
    }

    //NSLog(@"Final: theWord: %@, rvalue: %d, svalue: %d, direction: %d", theWord, rvalue, svalue, _direction);
    _numberOfTries = 0;
    _emergencyEnd = FALSE;
    _emergencyStart = FALSE;

    [self addWordToSearch:theWord theWord2:rvalue thervalue:svalue thesvalue:_direction];

}
}

The random direction array it refers to is:

- (void)createRandomDirectionArray
{
if (_horizontals < 4)
{
    //NSLog(@"-H");
    [_anArray addObject:@"3"];
    [_anArray addObject:@"7"];
}
if (_verticals < 4)
{
    //NSLog(@"-V");
    [_anArray addObject:@"1"];
    [_anArray addObject:@"5"];
}
if (_diagonals < 2)
{
    //NSLog(@"-D");
    [_anArray addObject:@"4"];
    [_anArray addObject:@"8"];
}
if (_backdiagonals < 2)
{
    //NSLog(@"-B");
    [_anArray addObject:@"2"];
    [_anArray addObject:@"6"];
}

[self.randomDirectionArray removeAllObjects];

for (int i = 0; i < [_anArray count]; i++)
{
    int r = arc4random() % [_anArray count];
    [self.randomDirectionArray addObject:[_anArray objectAtIndex:r]];
    [_anArray removeObjectAtIndex:r];
}

for (int i = 0; i < [self.randomDirectionArray count]; i++)
{
    //NSLog(@"Element %d: %d", i, [[self.randomDirectionArray objectAtIndex:i]intValue]);
}
}

And the gameWithWord method is:

- (void)gameWithWord:(NSString *)theWord
{
    [self randomCoordinates]; //GENERATES A PAIR OF RANDOM COORDINATES
    [self createRandomDirectionArray];

    _attempts ++; 
    [self checkWordToSearch:theWord rvalueToPick:_correctr svalueToPick:_corrects];
}

If anyone has any idea that would be much appreciated.


Solution

  • It appears that checkWordToSearch is calling gameWithWord, but gameWithWord also appears to call checkWordToSearch. If so, that sort recursion can cause the behavior you describe (crashing in seemingly random places).

    I'd suggest double checking the logic to make sure that it's exiting the recursive loop like you obviously intended. Or, better, change it so it's not calling itself recursively. And if you have to do this much without yielding back to the runloop, you might consider using an autorelease block within the loop.