为什么此代码会导致EXC_BAD_ACCESS错误?

时间:2012-05-02 20:58:50

标签: iphone objective-c xcode memory-management

这是我写的一段代码,用于清理一串不需要的字符和双倍间距。 但是,我似乎误解了某处的内存管理,并且它一直导致EXC_BAD_ACCESS错误。删除释放语句时,“代码”在功能上运行良好但会导致内存泄漏。

-(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;
}

如果我刚才问了一些非常明显的事情,请原谅我。

P.S。另一个问题。是否有必要发布NSRange?

4 个答案:

答案 0 :(得分:1)

就在这里

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

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

您丢弃原始对象并将其替换为自动释放的对象

当你致电

时会崩溃
[wantedCharacters release];

这样做

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

忘了最后一次

[wantedCharacters release];

答案 1 :(得分:0)

您的代码中有几个错误会导致您丢失对已分配对象的引用,并且会有一个示例,但有几点:

  1. 所有这些解决方案最简单的解决方案是,只要您调用autorelease,就可以使用alloc(并删除这些对象的release),例如:

    NSString* cleanStringOutput=[[[NSString alloc] initWithString:@""] autorelease];
    
  2. 当您创建一个仅在以后分配给它的变量时,不需要分配,例如:

    NSCharacterSet* wantedCharacters; // no need for alloc here
    wantedCharacters=[ NSCharacterSet characterSetWithCharactersInString:@"qwertyuiopasdfghjklzxcvbnm"];
    
  3. 一般情况下 - 如果您没有分配对象,则不会释放它。

答案 2 :(得分:0)

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

返回一个自动释放的字符串 - 无需在上面分配/初始化它。

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

所以打电话

[currentLetter release];

可能会导致问题。

答案 3 :(得分:0)

您分配/初始化wantedCharacters对象,然后使用便捷功能重新分配它。重新分配会使用第一个对象创建一个僵尸。

便捷功能将新对象实例放入自动释放池中。

然后你打电话给释放。由于它只保留一次,因此会被取消分配。

稍后,自动释放池会调用它的释放,但它已被解除分配。这会导致崩溃。