Charles
Charles

Reputation: 493

Why does this Code cause the EXC_BAD_ACCESS error?

Here's a piece of code I wrote for cleaning A string of unwanted chars and double spacing. However, I seem to have misunderstood memory management somewhere and it keeps causing the EXC_BAD_ACCESS error. The Code works fine functionally when the release statements are removed but that would cause memory leaks.

-(NSString*) cleaningString:(NSString*) input  {
NSCharacterSet* wantedCharacters=[[NSCharacterSet alloc] init];

   wantedCharacters=[ NSCharacterSet    
 characterSetWithCharactersInString:@"qwertyuiopasdfghjklzxcvbnm"];


NSString* cleanStringOutput=[[NSString alloc] initWithString:@""];
NSString* currentLetter =[[NSString alloc] initWithString:@" "];
NSRange unwantedCharacters=[currentLetter rangeOfCharacterFromSet:wantedCharacters];

for (int i=0; i<input.length; i++) {
    currentLetter=[NSString stringWithFormat:@"%c",[input characterAtIndex:i]];
    unwantedCharacters=[currentLetter rangeOfCharacterFromSet:wantedCharacters];
    doubleSpace=YES;
    if (i<input.length-1) {
        if (([currentLetter isEqualToString:@" "])&&([[NSString stringWithFormat:@"%c",[input characterAtIndex:i+1]] isEqualToString:@" "])) {
            doubleSpace=NO;}
    }
    else {
        if ([currentLetter isEqualToString:@" "]) {
            doubleSpace=NO;
        }
    }
    if ((unwantedCharacters.location!=NSNotFound)&&(doubleSpace))
    {
        cleanStringOutput=[NSString stringWithFormat:@"%@%@", cleanStringOutput, currentLetter];
    }
}
if (cleanStringOutput.length>0){
    if ([[NSString stringWithFormat:@"%c",[cleanStringOutput characterAtIndex:0]] isEqualToString:@" "]){
        cleanStringOutput=[cleanStringOutput substringFromIndex:1];
    }
}

[currentLetter release];
[wantedCharacters release];
[cleanStringOutput autorelease];
return cleanStringOutput;
}

Please forgive me if I just asked something painfully obvious.

P.S. And another question. Is it necessary to release the NSRange?

Upvotes: 1

Views: 414

Answers (4)

Jim
Jim

Reputation: 5960

You alloc/init a wantedCharacters object, then reassign it using a convenience function. The reassignment creates a zombie with the first object.

The convenience function puts the new object instance into the autorelease pool.

Then you call release. Since it was only retained once, it gets deallocated.

Later, the autorelease pool calls release on it, but it has already been deallocated. This causes the crash.

Upvotes: 0

Warren Burton
Warren Burton

Reputation: 17372

Right here

NSCharacterSet* wantedCharacters=[[NSCharacterSet alloc] init];

   wantedCharacters=[ NSCharacterSet    
 characterSetWithCharactersInString:@"qwertyuiopasdfghjklzxcvbnm"];

You discard your original object and replace it with an autoreleased one

Which will crash when you call

[wantedCharacters release];

Do this

NSCharacterSet* wantedCharacters=[ NSCharacterSet    
 characterSetWithCharactersInString:@"qwertyuiopasdfghjklzxcvbnm"];

and forget the last

[wantedCharacters release];

Upvotes: 1

mr-sk
mr-sk

Reputation: 13397

currentLetter=[NSString stringWithFormat:@"%c",[input characterAtIndex:i]];

Returns an autoreleased string - no need to alloc/init it above.

NSString* currentLetter =[[NSString alloc] initWithString:@" "];

So calling

[currentLetter release];

Will probably cause problems.

Upvotes: 0

MByD
MByD

Reputation: 137282

There are several mistakes in your code that causes you to lose the reference to the allocated objects, and an example will follow, but a few things:

  1. The easiest solution for all of them, is to use autorelease wherever you call alloc (and remove the release for those objects), for example:

    NSString* cleanStringOutput=[[[NSString alloc] initWithString:@""] autorelease];
    
  2. When you create a variable only to assign to it later, there is no need to allocate, for example:

    NSCharacterSet* wantedCharacters; // no need for alloc here
    wantedCharacters=[ NSCharacterSet characterSetWithCharactersInString:@"qwertyuiopasdfghjklzxcvbnm"];
    
  3. In general - if you didn't allocate the object, you don't release it.

Upvotes: 0

Related Questions