【问题标题】:Memory leak with NSStringNSString 的内存泄漏
【发布时间】:2011-07-06 23:23:35
【问题描述】:

我在这里阅读了几乎所有关于涉及 NSStrings 的内存管理的问题,但我无法真正解决这个问题。

@接口:

@property (nonatomic, retain) NSString *criticalTranscription;

@实现: viewDidLoad:

criticalTranscription = [[NSString alloc] init];

NSArray *paragraphs = [doc valueForKeyPath:@"critical.text"];
for(int i = 0; i < [paragraphs count]; i++) 
{
    criticalTranscription = [criticalTranscription stringByAppendingString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]];
    criticalTranscription = [criticalTranscription stringByAppendingString:@"\n\n"];
}
[transcription setText:criticalTranscription];

@XIB 带有 IBAction 的 UISegmentedControl 链接到:

- (IBAction) changeText:(id)sender
{
  if(transcriptionSelector.selectedSegmentIndex == 1)
    [transcription setText:diplomaticTranscription];
  else
    [transcription setText:criticalTranscription];
}

当我更改 UISegmentControl 的值时(加载后的第一件事,没有其他运行),我遇到了这个错误 (NSZombieEnabled=YES):

2011-07-07 01:10:43.639 Transcribe[404:707] *** -[CFString length]: message sent to deallocated instance 0x1189300

我在回溯中看不到任何相关内容。没有 NSZombieEnabled criticalTranscription 只是指向随机数组或其他东西。没有进一步使用该变量或任何版本。

我运行了分析,没有任何可疑的泄漏。

有什么问题?

【问题讨论】:

  • 你在哪里创建和设置diplomaticTranscription

标签: objective-c memory-management ios4 nsstring


【解决方案1】:

问题是您正在用您不拥有的字符串覆盖对您拥有的字符串的引用。

// you own the empty string returned here
criticalTranscription = [[NSString alloc] init]; 

NSArray *paragraphs = [doc valueForKeyPath:@"critical.text"];
for(int i = 0; i < [paragraphs count]; i++) 
{
    // immediately overwrite allocated instance (that you own)
    criticalTranscription = [criticalTranscription stringByAppendingString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]];
    criticalTranscription = [criticalTranscription stringByAppendingString:@"\n\n"];
}

但是,不要使用这种方法,因为它会用不必要的字符串污染自动释放池。相反,使用可变字符串并将字符串附加到单个可变字符串实例。

另外,为了利用属性的内置内存管理,您需要使用self.criticalTranscription 而不仅仅是criticalTranscription。如果没有self.,则直接使用实例变量。

【讨论】:

    【解决方案2】:

    在你的 for 循环中

    criticalTranscription = [criticalTranscription stringByAppendingString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]];
    criticalTranscription = [criticalTranscription stringByAppendingString:@"\n\n"];
    

    您将criticalTranscription 设置为一个自动释放的字符串对象,但没有保留它,因此是燃烧的死亡。

    您可以保留它或使用 @property(nonatomic, copy)NSString *criticalTranscription; 的属性并使用该属性而不是 ivar。

    【讨论】:

      【解决方案3】:

      两个问题:

      • 您正在泄漏字符串的第一个实例
      • 您分配给它的每个后续值都会自动释放

      要修复它,最简单的方法是将criticalTranscription 更改为 NSMutableString。然后你可以这样做:

      criticalTranscription = [[NSMutableString alloc] init];
      
      NSArray *paragraphs = [doc valueForKeyPath:@"critical.text"];
      for(int i = 0; i < [paragraphs count]; i++) 
      {
          [criticalTranscription appendString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]];
          [criticalTranscription appendString:@"\n\n"];
      }
      [transcription setText:criticalTranscription];
      

      ……或者,

      [criticalTranscription appendFormat:@"%@\n\n", [[paragraphs objectAtIndex:i] valueForKey:@"p"]];
      

      另请注意,完成后,您需要在criticalTranscription 上调用release,无论是在-viewDidLoad 的末尾还是在其对应的-viewDidUnload 中。

      【讨论】:

        猜你喜欢
        • 2011-10-31
        • 1970-01-01
        • 1970-01-01
        • 2012-10-29
        • 2014-06-06
        • 1970-01-01
        • 2011-10-05
        • 2011-07-31
        • 1970-01-01
        相关资源
        最近更新 更多