【问题标题】:NSImage TIFFRepresentation doesn't get released with ARCNSImage TIFFRepresentation 不会随 ARC 一起发布
【发布时间】:2012-05-05 22:39:22
【问题描述】:

我有一个处理数千张图像的 OSX Cocoa ARC 项目。为了减少图像的数量,我们扫描图像以查看它们是否是统一的颜色,如果是,我们将丢弃图像并跟踪其颜色。

获得纯色的代码是:

- (NSColor *)getSolidColor:(NSImage *)image
{
NSBitmapImageRep* raw_img = [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]];

int Bpr = [raw_img bytesPerRow],spp = [raw_img samplesPerPixel];
unsigned char *data = [raw_img bitmapData];
int w = [raw_img pixelsWide],h = [raw_img pixelsHigh];

uint32_t mask = 0x00FFFFFF;
uint32_t color = *((uint32_t *)data) & mask;

    for( int y=0; y<h; y++ ) 
    {
    unsigned char *p = data + Bpr*y;

        for( int x=0; x<w; x++ ) 
        {
            if( color != (*((uint32_t *)p) & mask) )
                return( nil );
            p += spp;
        }
    }

    return( [raw_img colorAtX:0 y:0] );
}

(为简洁起见删除了一些错误检查 - 上面的代码假设每个像素有 3 个样本。)

调用它的代码基本上是:

NSString *imageFile;
while( imageFile = [self getNextImageFile] )
{
NSImage *image = [[NSImage alloc] initWithContentsOfFile:imageFile];
    if( [image isValid] && [self getSolidColor:image] )
        [fileManager removeItemAtPath:imageFile error:nil];
}

问题在于应用程序消耗了大量的内存。当我在分析器中运行它时,它表明所用内存的 90% 是由 [NSImage TIFFRepresentation] 分配的(上面加粗)。

即TIFFRepresentation 数据和 NSBitmapImageRep 永远不会被释放,即使它们在函数返回后立即超出范围。

为什么?我应该/可以做些什么来强制 ARC 释放这些块?

使用非 ARC 的“旧方式”,我只需在图像的 while 循环内放置一个自动释放池,这样就可以解决问题。 ARC有这样的概念吗?

谢谢。

(PS。NSZombies 未启用。)

【问题讨论】:

  • 指出所有这些都发生在后台线程中可能是相关的。当线程退出时,所有内存都被正确释放,就像自动释放池一样。

标签: macos cocoa memory memory-leaks automatic-ref-counting


【解决方案1】:

从概念上讲,ARC 仍然可以使用自动释放池,只是不能再使用 NSAutoreleasePool 类。

改用新的@autoreleasepool 关键字:

@autoreleasepool {
   //Do stuff that you previously would have wrapped in an NSAutoreleasePool...
}

【讨论】:

  • 确实!!!刚刚在这里也发现了stackoverflow.com/questions/9770213/arc-memory-leaks
  • 为了清楚起见,OSX 框架似乎没有使用 ARC(至少没有完全使用),因此 API 调用仍然需要一个自动释放池,并用 @autoreleasepool 包装循环内部解决了这个问题。
  • @KevinFranklin:框架是否使用 ARC 无关紧要(按设计);当您创建一个线程时,您负责放置一个自动释放池以捕获在该线程上自动释放的任何对象。 (如果您没有在控制台中收到关于此的日志消息,我会感到惊讶。)
  • 确实有很多线程并且没有在它们周围使用自动释放池,并且没有收到任何关于它的警告或任何内存泄漏。我只是假设现在正在为我处理这件事?
  • @KevinFranklin:你(或正在)如何创建线程?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 2013-03-22
  • 1970-01-01
相关资源
最近更新 更多