【问题标题】:Reusing NSMutableArray重用 NSMutableArray
【发布时间】:2011-01-08 21:20:14
【问题描述】:

在尝试重用现有 NSMutableArray(以节省内存)时,我遇到了一些泄漏(由 Instruments 观察到)。

基本上我正在创建一个 NSMutableArray,用对象 (UIImages) 填充它并将它传递给另一个保留它的对象。但是,我现在需要再次使用 NSMutableArray。我想我会释放它的所有对象,清空它,一切都会好起来的,但 Instruments 会从该方法报告一个 CALayer 泄漏对象 (??),如下所示:

NSString *fileName;
NSMutableArray *arrayOfImages = [[NSMutableArray alloc] init];

// fill the array with images
for(int i = 0; i <= 7; i++) {
    fileName = [NSString stringWithFormat:@"myImage_%d.png", i];
    [arrayOfImages addObject:[UIImage imageNamed:fileName]];
}

// create a button with the array
aButton = [[CustomButtonClass buttonWithType:UIButtonTypeCustom] 
                   initWithFrame:someFrame
                   imageArray:arrayOfImages];

// release its objects
for(int i = 0; i < [arrayOfImages count]; i++) {
    [[arrayOfImages objectAtIndex:i] release];
}
// empty array
[arrayOfImages removeAllObjects];

// fill it with other images
for(int i = 0; i <= 7; i++) {
    fileName = [NSString stringWithFormat:@"myOtherImage_%d.png", i];
    [arrayOfImages addObject:[UIImage imageNamed:fileName]];
}
// create another button with other images (same array)
aSecondButton = [[CustomButtonClass buttonWithType:UIButtonTypeCustom] 
                   initWithFrame:someFrame
                   imageArray:arrayOfImages];

[arrayOfImages release];

为了清楚起见,我的按钮初始化方法如下所示:

- (id)initWithFrame:(CGRect)frame 
      images:(NSArray *)imageArray
{
    if(self = [super initWithFrame:frame]) {
        myImageArray = [[NSArray arrayWithArray:imageArray] retain];
    }
return self;
}

我知道我可以创建一个新的 NSMutableArray 并结束这个问题,但不能重用旧数组让我很恼火。可能是什么问题?

【问题讨论】:

    标签: objective-c cocoa release nsmutablearray reusability


    【解决方案1】:

    Leaks 工具会告诉您泄漏的对象首先分配的位置。其中一张图片被泄露的事实意味着您在其他地方使用了该图片,并且没有在那里发布 - 泄漏无法告诉您在哪里,因为它无法向您显示不存在的代码。

    确实,正如其他人所指出的那样,这有点令人惊讶,因为按原样的代码会过度释放对象并且应该崩溃。但它没有崩溃的事实是在其他地方使用数组中的图像并过度保留它们的好兆头。

    【讨论】:

      【解决方案2】:

      我得到了一些泄漏(观察到 Instruments) 当试图重用一个 现有的 NSMutableArray(为了 节省内存)。

      数组占用的内存非常少;每个指针存储 4 个字节(在 32 位系统上)+ 一点点开销。除了最特殊的情况外,重用数组来尝试节省内存在所有情况下都是浪费时间。

      // release its objects
      for(int i = 0; i < [arrayOfImages count]; i++) {
          [[arrayOfImages objectAtIndex:i] release];
      }
      // empty array
      [arrayOfImages removeAllObjects];
      

      您没有保留这些对象,因此,您不应该释放它们!您的应用在执行上述操作后没有崩溃表明您可能在其他地方过度保留了对象。

      我知道我可以创建一个新的 NSMutableArray 并结束这个 问题,但我无法做到 只是重用旧数组。什么 可能是问题吗?

      该代码中没有任何内容会导致内存泄漏。恰好相反;你过度释放对象。

      以上表明您确实需要重新访问memory management guidelines,因为重新使用数组而不是释放数组并创建一个新数组与这个问题没有任何关系。

      【讨论】:

      • 非常感谢这个非常描述性的答案!
      【解决方案3】:

      你不需要这部分:

      // release its objects
      for(int i = 0; i < [arrayOfImages count]; i++) {
          [[arrayOfImages objectAtIndex:i] release];
      }
      

      这违反了所有权规则。您没有在

      保留图像
      [arrayOfImages addObject:[UIImage imageNamed:fileName]];
      

      因此释放它们不是您的责任。当-addObject 被调用时,NSMutableArray 会保留它们,所以NSMutableArray 有责任在-removeObject 或其他类似函数被调用时释放它们。您发现的泄漏可能是因为系统被这种过度释放弄糊涂了......

      我还建议在 XCode 中执行“构建和分析”。

      【讨论】:

        猜你喜欢
        • 2016-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多