EXC_BAD_ACCESS error


#1

why is this code throwing: Thread 1: EXC_BAD_ACCESS (code=2, address=…)
and not logging 2nd array (newStrings). I am using Xcode 4.4 (on Mountain Lion)

[code] // create an array of strings to devowelize and a container for new ones
NSArray *oldStrings = [NSArray arrayWithObjects:@“Sauerkraut”, @“Raygun”, @“Big Nerd Ranch”, @“Mississippi”, nil];
NSLog(@“old strings: %@”, oldStrings);
NSMutableArray *newStrings = [NSMutableArray array];

    // create a list of characters that we'll remove from the string
    NSArray *vowels = [NSArray arrayWithObjects:@"a", @"e", @"i", @"o", @"u", nil];
    
    // declare the block variable
    void (^devowelizer)(id, NSUInteger, BOOL *);
    
    // assign a block to the variable
    devowelizer = ^(id string, NSUInteger i, BOOL *stop) {
      
        NSMutableString *newString = [NSMutableString stringWithString:string];
        
        // iterate over the array of vowels, replacing occurrences of each
        // with empty string.
        for (NSString *s in vowels) {
            NSRange fullRange = NSMakeRange(0, [newString length]);
            [newString replaceOccurrencesOfString:s
                                       withString:@""
                                          options:NSCaseInsensitiveSearch
                                            range:fullRange];
        }
        [newStrings addObject:newStrings];
    }; // end of block assignment

    // Iterate over the array with our block
    [oldStrings enumerateObjectsUsingBlock:devowelizer];
    NSLog(@"new strings: %@", newStrings);[/code]

#2

I won’t exactly tell you what the problem is, but I will show you the culprit (inside the devowelizer block):

[newStrings addObject:newStrings];

Can you see what’s wrong?


#3

[quote=“ibex10”]I won’t exactly tell you what the problem is, but I will show you the culprit (inside the devowelizer block):

[newStrings addObject:newStrings];

Can you see what’s wrong?[/quote]

wow. This is embarrassing. :slight_smile: Thank you!


#4

Good. But can you explain how this causes the crash?


#5

some kind of recursion that never ends?

I don’t know why does it cause a crash?


#6

Yes. But where?


#7

newStrings assigned a new object which is itself, as such the object also contains the new object of itself along with the new object of it self contained there in, which also contains the object newStrings, and so on to infinity or until memory runs out.

Is this right?


#8

No, that’s not correct.

But, look at this log statement:

NSLog (@"new strings: %@", newStrings);

How does NSLog print the newStrings?


#9

that makes sense! I kinda threw that out there, knowing I don’t have a clear grasp yet.

Ok, the call is

{newStrings addObject:newStrings];

Which will take the pointer to the object newStrings, and add it to the array of objects contained in the same array “newStrings”, which is really an array of pointers to objects.

So all you end up with after the call executes is newStrings with one extra object appended, a pointer which points back to itself.

Now to your Question.

That makes sense to me
NSLog prints out the description of the object, which for an array is


description
Returns a string that represents the contents of the array, formatted as a property list.

  • (NSString *)description
    Return Value
    A string that represents the contents of the array, formatted as a property list.

Availability
Available in iOS 2.0 and later.
See Also
– descriptionWithLocale:
– descriptionWithLocale:indent:
Declared In
NSArray.h


Now since the array newStrings has a pointer which points back to itself, NSLog prints in this loop for ever and ever.
My guess is, that its within NSLog where it finally breaks.

is this right?


#10

That’s correct.


#11

it’s an interesting bug, it’ll be nice, when I am fluent enough to spot these on my own.

Thank you so much for the education.


#12

Is this an example of a stack over run?

Because, how I imagine NSLog works, is that it first assembles the string before it outputs, and it is within that algorithm that the stack would over run.
I think that because I am under the impression that the stack is much faster to manipulate then is the heap.
So it makes sense that NSLog assemble its output using the stack.

Is this right?