为方便起见,我已使用一些工作代码编辑了上一篇文章。
以下代码(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 = color,并且没有这样的泄漏。
我也可以这样做:
[[self.nsBackColor objectAtIndex:x] replaceObjectAtIndex:y withObject:[self description]];
我得到同样的泄漏。
在我看来,对象在数组中被替换(是的,这最初是作为2D c数组开始的,但我认为这是问题)永远丢失和泄露并且没有正确释放。
这将是在短时间内运行后的仪器 - >分配:
非常感谢任何帮助,可以提供更多信息。
答案 0 :(得分:0)
发生的事情是您在每次迭代时都在创建自动释放池。 因此,每次使用新的自动释放池运行以下行:
[[self.nsBackColor objectAtIndex:x] replaceObjectAtIndex:y withObject:color];
因此color
将本地池中的引用计数增加1,而[[self.nsBackColor objectAtIndex:x] objectAtIndex:y]
将本地池中的引用计数减少1。但是这里有一个问题:在上一次迭代中,该项目为color
,其引用计数由之前排空/释放的前一个池管理。
所以应该发生的事情就是在前一次迭代中发布了前一个池,该对象被释放了。它的引用计数为2(一个用于[UIColor colorWith...]
,一个用于添加到数组中),因此一旦池耗尽就应该收到2个释放消息,并且应该留下[[self.nsBackColor objectAtIndex:x] objectAtIndex:y]
中的指针悬挂,直到您在当前迭代中使用指向color
的指针替换它。
显然,这种情况并没有完全按照预期的方式发生,或者我理解它的方式。但是,@autoreleasepool {}
指令显然是错位的。它应该在while (true)
循环周围,或者完全删除,以支持线程的池。