简体   繁体   English

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

[英]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. 但是,我似乎对某个地方的内存管理有误解,并且一直导致EXC_BAD_ACCESS错误。 The Code works fine functionally when the release statements are removed but that would cause memory leaks. 删除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;
}

Please forgive me if I just asked something painfully obvious. 如果我刚刚问过一些显而易见的事情,请原谅我。

PS And another question. PS和另一个问题。 Is it necessary to release the NSRange? 是否需要释放NSRange?

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];

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: 对于所有这些对象,最简单的解决方案是在调用alloc任何地方使用autorelease (并删除这些对象的release ),例如:

     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. 通常,如果不分配对象,则不会释放它。

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. 可能会引起问题。

You alloc/init a wantedCharacters object, then reassign it using a convenience function. 您分配/初始化一个wantedCharacters对象,然后使用便捷函数重新分配它。 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. 这会导致崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM