MutableCopy AllocLeak内存泄漏

时间:2013-01-22 22:29:44

标签: iphone ios objective-c memory-management nsmutablecopying

我有一个每秒触发一次的NSTimer。

每一秒我都有一个需要更改的NSString。

我之前从未尝试过处理内存管理,因此我不确定我所做的是否正确,但是仪器在“alloc”下说stringByReplacingOccurrencesOfString的代码行有45MB大约一分钟后“活字节”......

(实时字节数每秒都在不断上升,最终导致应用程序崩溃)。

我认为我的问题出在MutableCopy代码的某个地方?

这是我的代码:

-(void)myTimer {
    if (testedit) {
        [testedit release];
        [withString1a release];
        [forString1a release];
    }
    testedit = [[NSString alloc] init];
    withString1a = [[NSString alloc] init];
    forString1a = [[NSString alloc] init];

    testedit = [[NSString alloc] initWithFormat:@"example"];
    withString1a = [[NSString alloc] initWithFormat:@"e"];//this string gets its values randomly from an array in my real code
    forString1a = [[NSString alloc] initWithFormat:@"flk34j"];//this string gets its values randomly from an array in my real code

    testedit = [[testedit stringByReplacingOccurrencesOfString:withString1a withString:forString1a]  mutableCopy];//memory leak /:

}

4 个答案:

答案 0 :(得分:2)

您要为每个对象分配两次内存。当您第二次分配并将其分配给同一个变量时,第一块alloc'd内存将变得无法访问且无法释放。

然后你制作一个testsable的mutableCopy并将副本分配给原始变量。再一次,你留下了一块无法访问的内存。

非ARC内存管理的规则是 - 对于每个 alloc new copy 保留您需要有相应的发布。你有6个分配,一个副本,只有3个版本。

以下是一些建议。

删除这些重复的分配:

   testedit = [[NSString alloc] init];
   withString1a = [[NSString alloc] init];
   forString1a = [[NSString alloc] init];

据推测,testeditwithString1aforString1a都是iVars。 (Please declare your iVars as autosynthesized properties并将它们称为self.testedit ...等,这将使您的代码更清晰地堆叠溢出程序)。

取出所有这些:

if (testedit) {
        [testedit release];
        [withString1a release];
        [forString1a release];
    }

假设这些都是iVars,释放它们的正确位置在对象的dealloc方法中

事实上,withString1aforString1a可以是本地变量,因为您可以从其他地方获取内容:

 NSString*  withString1a = [[[NSString alloc] initWithFormat:@"e"] autorelease];
 NSString*  forString1a =  [[[NSString alloc] initWithFormat:@"flk34j"] autorelease];

你可以autorelease他们,因为你不需要他们在方法完成后闲逛。

这些行也可以写成:

 NSString*  withString1a = [NSString stringWithFormat:@"e"];
 NSString*  forString1a =  [NSString stringWithFormat:@"flk34j"];

( - stringWithFormat是一种返回自动释放对象的便捷方法)

这给我们留下了这两条线。

  testedit = [[NSString alloc] initWithFormat:@"example"];
  testedit = [[testedit stringByReplacingOccurrencesOfString:withString1a 
                                                  withString:forString1a]  mutableCopy];

目前尚不清楚为什么将testit视为第一行中的不可变字符串和第二行中的可变字符串。您根本不需要可变字符串,因为您要用新字符串替换testedit

 self.testedit = [[NSString alloc] initWithFormat:@"example"];
 self.testedit = [[testedit stringByReplacingOccurrencesOfString:withString1a 
                                                  withString:forString1a] copy]; 

(您需要copy,因为stringByReplacingOccurrencesOfString:withString:会返回一个自动释放的对象,在这里您要保留它)

最后一块拼图正在摆脱你的_testedit iVar内存分配。您可以在对象的dealloc方法中执行此操作:

- (void) dealloc {
    [_testEdit release];
    [super dealloc];
}

(请注意,init,访问者和dealloc方法是使用属性语法引用iVar的三个地方。)

一切都很好,但实际上,你应该使用ARC!与使用编译器为您管理内存相比,您更容易以这种方式引入内存错误。

答案 1 :(得分:1)

我建议你在这里使用@property

在.h文件中将属性声明为:

@property (nonatomic, retain) NSString *testedit;
@property (nonatomic, retain) NSString *withString1a;
@property (nonatomic, retain) NSString *forString1a; //if required write the @synthesize as well in .m class

您可以将计时器方法编写为:

-(void)myTimer {

    self.testedit = @"example";
    self.withString1a = @"e";//this string gets its values randomly from an array in my real code
    self.forString1a = @"flk34j";//this string gets its values randomly from an array in my real code
    self.testedit = [self.testedit stringByReplacingOccurrencesOfString:self.withString1a withString:self.forString1a];
}

在dealloc方法中,您可以将以上所有属性设置为nilself.testedit = nil;)或对其进行发布([testedit release];)。

如果可能,尝试切换到ARC,您不必担心内存管理。你的代码的问题在于你在使用大量的alloc / init语句而没有在执行之前释放变量。这会导致它丢失该变量的引用,您将泄漏它。你不需要那么多的分配语句。对于每个分配或保留,应该有相应的发布/自动释放语句。

答案 2 :(得分:0)

您正在收到内存泄漏,因为您从未取消分配testedit。每当你调用alloc时,这意味着你需要释放它。这通常只意味着调用release

执行类似的操作,然后确保释放已分配的内存:

NSString* newString = [[testedit stringByReplacingOccurrencesOfString:withString1a withString:forString1a]  mutableCopy];

答案 3 :(得分:0)

如果您使用ARC,则不应该有问题。如果您不使用ARC,可以尝试添加autorelease

testedit = [[[testedit stringByReplacingOccurrencesOfString:withString1a withString:forString1a]  mutableCopy] autorelease];