【问题标题】:Why does this Code cause the EXC_BAD_ACCESS error?为什么此代码会导致 EXC_BAD_ACCESS 错误?
【发布时间】:2012-05-02 20:58:50
【问题描述】:

这是我为清理一串不需要的字符和双倍间距而编写的一段代码。 但是,我似乎在某处误解了内存管理,它不断导致 EXC_BAD_ACCESS 错误。删除 release 语句后,代码可以正常工作,但这会导致内存泄漏。

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

如果我只是问了一些非常明显的问题,请原谅我。

附:还有一个问题。是否需要释放 NSRange?

【问题讨论】:

  • 我的建议--> 看看developer.apple.com/library/mac/documentation/Cocoa/Conceptual/… 从长远来看这将对您有所帮助..
  • 你有一个基本问题,它可以很好地说明其他人了解它是什么。这不仅仅是一个“修复我的 codz”问题。我认为它不应该被否决。看起来 Warren Burton 为你确定了它。
  • 我只是没有意识到返回的对象是自动释放的。我有一些java经验,但没有保留和释放内存管理......
  • 它不会因为被退回而自动释放。如果这是您想要或需要的,您必须将其设置为自动发布。通常,您确实希望自动释放退回的物品。
  • 仅供参考:并非 所有 返回的对象都是自动释放的 - 例如 mutableCopy 返回您拥有的对象(因此必须释放自己)。经验法则 - 如果方法是 aloc/initcopymutableCopynew,您拥有它并且必须释放它。否则,它会自动发布。当您对引用计数和内存管理有了更多了解后,我衷心建议您开始使用 ARC - 它可以为您处理大部分内容:)

标签: iphone objective-c xcode memory-management


【解决方案1】:

就在这里

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

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

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

调用时会崩溃

[wantedCharacters release];

这样做

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

忘记最后一个

[wantedCharacters release];

【讨论】:

  • 谢谢!我对 Objective C 的内存管理还很陌生,所以我没有意识到 return 语句是自动释放的。
【解决方案2】:

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

  1. 最简单的解决方案是在调用alloc 的任何地方使用autorelease(并删除这些对象的release),例如:

    NSString* cleanStringOutput=[[[NSString alloc] initWithString:@""] autorelease];
    
  2. 当你创建一个变量只是为了以后分配给它时,不需要分配,例如:

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

【讨论】:

  • 应用自动释放和不正确地学习内存管理不是一个很好的长期修复 IMO。
【解决方案3】:
currentLetter=[NSString stringWithFormat:@"%c",[input characterAtIndex:i]];

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

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

所以打电话

[currentLetter release];

可能会导致问题。

【讨论】:

    【解决方案4】:

    您分配/初始化一个wantedCharacters 对象,然后使用便利函数重新分配它。重新分配使用第一个对象创建一个僵尸。

    便利函数将新对象实例放入自动释放池。

    然后你调用释放。由于它只保留了一次,因此它会被释放。

    稍后,自动释放池对其调用释放,但它已被释放。这会导致崩溃。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-31
      • 1970-01-01
      • 2023-04-02
      • 2011-03-16
      • 1970-01-01
      • 1970-01-01
      • 2012-01-15
      相关资源
      最近更新 更多