【问题标题】:Leak in NSMutableArrayNSMutableArray 中的泄漏
【发布时间】:2011-10-15 06:15:33
【问题描述】:

我一直在拔头发,想弄清楚为什么会漏水。在我的 .h 文件中,我有一个综合属性 nonatomic,保留 NSMutableArray。在我的 viewDidLoad 中,我将其声明为:

self.tableData = [[NSMutableArray alloc] init];
[self.tableData removeAllObjects];
fillData(self.tableData);

在整个应用程序中,我调用 [self.tableData removeAllObjects],然后使用 fillData(self.tableData) 函数重新填充它。此函数从静态 C++ 字符串集中填充数据:

void fillData(NSMutableArray* list)
{
    for (set<string>::const_iterator itr = sortedData.begin(); itr != sortedData.end(); ++itr){
        [list addObject:[NSString stringWithFormat:@"%s", ((string)*itr).c_str()]];
    }
}

在我的 dealloc 方法中我这样做:

[self.tableData removeAllObjects], [self.tableData release], tableData = nil;

我在哪里丢球了? Instruments 说它在 [list addObject....] 行中。

谢谢

【问题讨论】:

  • 你的((string)*itr).c_str() 调用不是返回一个不是自动释放的字符串吗?
  • 是的,但是它被复制到一个应该自动释放的 NSString 中。所以我不确定这是如何导致泄漏的。我需要分配/自动释放该 NSString 吗?
  • 看起来不错。如果将行一分为二,分成const char*s=(*itr).c_str(); [list addObject:[NSString stringWithUTF8String:s];,会发生什么?
  • 顺便说一句,不鼓励在stringWithFormat:中使用@"%s",因为不能指定使用的编码,这是非常危险的。例如,它可能会突然停止在俄罗斯 iPhone 上工作。使用stringWithUTF8String:stringWithCString:encoding:error:

标签: iphone objective-c memory-management nsmutablearray


【解决方案1】:
self.tableData = [[NSMutableArray alloc] init];
[self.tableData removeAllObjects];
fillData(self.tableData);

alloc +1 保留,为使用属性的设置器+1 保留。你还没有平衡来自alloc 的 +1。如果你要使用 setter:

self.tableData = [NSMutableArray array];
fillData(self.tableData);

请注意,removeAllObjects 完全没有意义。

这也很奇怪:

[self.tableData removeAllObjects], [self.tableData release], tableData = nil;

首先,不要费心移除对象。当数组被释放时,它会释放所有对象。其次,使用setter调用release然后立即做直接赋值是不一致的。要么做:

self.tableData = nil;

或者:

[tableData release], tableData = nil;

(请注意,在所有这些中使用, 也纯粹是为了您的利益——它对生成的代码没有影响。)

另外,使用stringWithUTF8String: 而不是stringWithFormat:

【讨论】:

    【解决方案2】:

    不确定是否是 泄漏,但这看起来是个问题:

    self.tableData = [[NSMutableArray alloc] init];
    

    您说tableData 是保留的属性。试试:

    self.tableData = [NSMutableArray arrayWithCapacity:10];
    

    这样属性会保留它,并且数组本身会自动释放。您在dealloc 中的发布将使保留计数降为零。

    【讨论】:

    • 除非您准确且始终知道会有多少项目,否则不要打扰arrayWithCapacity:。即便如此,它在很大程度上只是代码中的混乱,并且没有提供任何导入的实际优势。
    【解决方案3】:

    问题是您的属性设置为保留,而您将其设置为已保留的对象。 你应该这样做:

    // viewDidLoad
    NSMutableArray *array = [[NSMutableArray alloc] init];
    self.tableData = array;
    [array release]; // this is important
    
    // dealloc
    self.tableData = nil; // will automatically release the array
    

    【讨论】:

      【解决方案4】:

      在您的 dealloc 中,您使用再次保留 tableData 的属性。这不是你真正想要的,所以这样做:

      [tableData release];
      

      [self->tableData release]; // not necessary, but some prefer it.
      

      self.tableData = nil; // property will handle release
      

      无需清除 tableData,无需将任何内容设置为 nil(您正在解除分配,因此不会再访问它)。

      【讨论】:

        猜你喜欢
        • 2012-05-17
        • 2011-03-06
        • 1970-01-01
        • 2013-02-11
        • 2012-07-29
        • 2011-01-21
        • 2011-03-23
        • 2011-05-27
        • 2011-05-20
        相关资源
        最近更新 更多