objc泄漏行为我无法解释

时间:2010-11-13 03:28:13

标签: objective-c cocoa macos

以下代码循环不会泄漏内存(通过在“top”下无限循环来验证);

NSBitmapImageRep *this_bmap = 0;

while (1) {

  CGImageRef windowImage = 
     CGWindowListCreateImage(CGRectNull,
                             kCGWindowListOptionIncludingWindow,
                             windowID, kCGWindowImageDefault);

  this_bmap = [[NSBitmapImageRep alloc] initWithCGImage:windowImage];

  [this_bmap release];
  CGImageRelease(windowImage);
}

我不希望这样。但是,当我将指针复制到位图数据时,如下所示:

NSBitmapImageRep *this_bmap = 0;

while (1) {

  CGImageRef windowImage = 
     CGWindowListCreateImage(CGRectNull,
                             kCGWindowListOptionIncludingWindow,
                             windowID, kCGWindowImageDefault);

  this_bmap = [[NSBitmapImageRep alloc] initWithCGImage:windowImage];

  void *pixels1 = [this_bmap bitmapData];

  [this_bmap release];
  CGImageRelease(windowImage);
}
现在,这就像疯了一样泄漏。我可以看到这种情况在“顶层”下迅速发生,程序最终会停止。

我是Objective-C的新手,但我不是编程的新手,我无法理解这种行为。方法bitmapData的文档声称它只返回一个指针(而不是分配一些东西),所以我很难过。我从前段时间发现了一个类似的问题,但唯一的答案是“调查池”,我不知道这对我们有什么帮助。

有什么想法在这里发生了什么?

3 个答案:

答案 0 :(得分:7)

访问像素数据会使对象保留并自动释放,以便位图数据不会突然意外消失。要查看预期结果(即,每次迭代循环不消耗内存),请重写为:

NSBitmapImageRep * this_bmap = 0;

while (1) {
  NSAutoreleasePool* loopPool = [NSAutoreleasePool new];
  CGImageRef windowImage = 
     CGWindowListCreateImage(CGRectNull,
                             kCGWindowListOptionIncludingWindow,
                             windowID, kCGWindowImageDefault);

  this_bmap = [[NSBitmapImageRep alloc] initWithCGImage:windowImage];

  void *pixels1 = [this_bmap bitmapData];

  [this_bmap release];
  CGImageRelease(windowImage);
  [loopPool drain];
}

答案 1 :(得分:0)

嗯,我不是大师所以我只是在这里猜测。但是我发现每次循环都会有效地声明一个名为pixels1的新变量。因此,每次通过你分配一些新空间而不是重用它。尝试在循环外部移动像素1的声明,看看会发生什么。

注意,这只是猜测,可能是错误的。一个知识渊博的人可能会给你一个明确的答案。

答案 2 :(得分:0)

“initWithCGImage:”调用在其文档中有这个:

  

讨论

     

如果你使用这种方法,那么你   应该处理结果位图   NSBitmapImageRep对象为只读。   因为它只保留了价值   cgImage参数,而不是   解压缩数据,访问数据   像素数据需要创建一个   内存中的数据副本。变化   该数据不会保存回来   核心图形图像。

这似乎表明从bitmapData返回的内存需要CFRelease'ed。