2013-02-26 54 views
4

为了方便起见,我已经使用一些工作代码编辑了上一篇文章。NSMutableArray replaceObjectAtIndex:withObject循环泄漏

后续代码(ARC'ed)似乎泄漏,而且时间很短一段时间的磨合后会崩溃的SIM卡或设备:

#define kROWS 100 
#define kCols 34 

void run(); 

static ViewController *instance; 

@interface ViewController() 
@property (nonatomic, strong) NSMutableArray *nsBackColor; 
@end 

@implementation ViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 
    self.nsBackColor = [NSMutableArray arrayWithCapacity:1]; 
    instance = self; 

    // set up a '2D array' 
    for (int x = 0; x < kROWS; x++) { 
     [self.nsBackColor addObject:[NSMutableArray arrayWithCapacity:1]]; 
     for (int y = 0; y < kCols; y++) { 
      [[self.nsBackColor objectAtIndex:x] addObject:[UIColor whiteColor]]; 
     } 
    } 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     run(); 
    }); 
} 

- (void)plotColor:(UIColor *)color atX:(short)x andY:(short)y { 
    [[self.nsBackColor objectAtIndex:x] replaceObjectAtIndex:y withObject:color]; 
} 

- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

@end 

void plot(short xLoc, short yLoc, 
       short backRed, short backGreen, short backBlue) { 

    @autoreleasepool { 
     [instance plotColor:[UIColor colorWithRed:((float)backRed/100) 
              green:((float)backGreen/100) 
              blue:((float)backBlue/100) 
              alpha:(float)1] 
         atX:xLoc andY:yLoc]; 
    } 
} 

void run() { 
    short x = 0; 
    short y = 0; 
    short backRed = 0; 
    short backGreen = 0; 
    short backBlue = 0; 

    while (true) { 
     x++; 
     if (x >= kROWS) { 
      x = 0; 
     } 

     y++; 
     if (y >= kCols) { 
      y = 0; 
     } 

     backRed = arc4random() % 255; 
     backBlue = arc4random() % 255; 
     backGreen = arc4random() % 255; 

     plot(x, y, backRed, backGreen, backBlue); 

     usleep(1000); 
    } 
} 

如果我让设备或模拟器上运行这个足够长的时间(几分钟)我会收到一个mmap malloc错误(sim)或一个内存警告(设备)并崩溃。

通过仪器分配我可以看到+ [UIColor colorWithRed:green:blue:alpha:]开始气球直到最后敲击记忆墙。

我可以指定UIColor属性(直接或通过复制),说self.myColor =颜色,并没有这样的泄漏。

我也可以这样做:

[[self.nsBackColor objectAtIndex:x] replaceObjectAtIndex:y withObject:[self description]]; 

,我也得到相同的泄漏。

在我看来,在数组中替换的对象(是的,这最初是作为一个2D C数组开始的,但我认为这是问题)永远丢失并泄漏,没有正确释放。

这将是仪器 - >拨款的短时间运行后:

Instruments

任何帮助将是非常赞赏,并且可以提供更多的信息。

+0

你看过仪器中的这个确认你对泄漏的怀疑吗? – 2013-02-26 01:30:16

+0

你打赌。新增了一张图片。 – Sandoze 2013-02-26 02:02:35

+0

主runloop何时有机会耗尽自动释放池? 'usleep'是允许的,还是'while(true)'会阻止主runloop清除autorelease池? – 2013-02-26 03:12:26

回答

0

发生什么事是您在每次迭代中创建自动释放池。 所以以下行运行一个新的自动释放池每次:

[[self.nsBackColor objectAtIndex:x] replaceObjectAtIndex:y withObject:color]; 

因此color一个增加了局部池内其引用计数,而[[self.nsBackColor objectAtIndex:x] objectAtIndex:y]减一本地池中它的引用计数。但是这里有一个问题:在上一个迭代中,该项目是color,它的引用计数由之前排出/释放的上一个池管理。

因此,应该发生的事情是上一次迭代发布前一个池时,该对象被释放。它的引用计数是2(一个用于[UIColor colorWith...],一个用于添加到数组中),所以一旦池被耗尽,它应该收到2个释放消息,并且[[self.nsBackColor objectAtIndex:x] objectAtIndex:y]中的指针应该悬空,直到在当前替换为止用指向color的指针迭代。

很明显,这并不是完全按照它应该的方式或我理解它的方式发生的。但是,@autoreleasepool {}指令明显错位。它应该在while (true)循环周围,或者完全移除以支持线程池。