1

在尝试重用现有 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 并结束这个问题,但是不能重用旧数组让我很恼火。可能是什么问题呢?

4

3 回答 3

6

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

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

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

您没有保留对象,因此,您不应该释放它们!在上述情况之后您的应用程序没有崩溃表明您可能在其他地方过度保留了对象。

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

该代码中没有任何内容会作为内存泄漏而出现。恰好相反; 你过度释放对象。

以上表明您确实需要重新访问内存管理指南,因为重用数组而不是释放数组并创建新数组与这个问题没有任何关系。

于 2010-01-25T03:53:58.470 回答
4

你不需要这部分:

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

这违反了所有权规则。你没有保留图像

[arrayOfImages addObject:[UIImage imageNamed:fileName]];

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

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

于 2010-01-24T23:05:22.567 回答
0

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

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

于 2010-01-25T04:35:30.040 回答