如何修复CFRuntimeCreateInstance对象泄漏?

时间:2011-08-10 21:53:52

标签: iphone objective-c object memory-leaks

在使用仪器泄漏工具分析我的应用程序时,我遇到了看不见的对象泄漏(CFRuntimeCreateInstance)。我有粗暴的想象力,泄漏发生但无法发现它:)调用树指向我的类方法从spritesheet加载图像。这是调用树的一个片段(直到泄漏对象CFRuntimeCreateInstance):

+[ImageCache loadImageOfType:andIndex:]
 +[NSString stringWithFormat:]
  _CFStringCreateWithFormatAndArgumentsAux
   CFStringCreateCopy
    __CFStringCreateImmutableFunnel3
     _CFRuntimeCreateInstance

我正在使用这个辅助类方法来加载和缓存图像。该方法使用静态NSMutableDictionary,它推送加载的图像以供进一步使用。我的图像被分组为spritesheets,因此该方法读取相应的图像文件并读取相应的图像区域。这是我的方法:

+(UIImage*)loadImageOfType:(int)type andIndex:(int)index{
  UIImage *image;

  if (!dict) dict = [[NSMutableDictionary dictionary] retain];

  //First, trying to get already loaded image
  int ind = IMAGECOUNT * type + index; //calculating the index that is used for storing image in dict
  image = [dict objectForKey:[NSString stringWithFormat:@"%d", ind]]; //trying to get image
  if (!image){ //if image is not loaded then read the spriteimage file 
    NSString *spritesheetName = [NSString stringWithFormat:@"itemsprite%d.png", type];
    NSString* imagePath = [[NSBundle mainBundle] pathForResource:spritesheetName ofType:nil];
    image = [UIImage imageWithContentsOfFile:imagePath];
    if (image) //if spritesheet exists
    {
        int loopInd; 
        CGFloat x = 0, y = 0;
        //load all images from it
        for (int i=0; i<IMAGECOUNT; i++) {
            UIImage *img;
            loopInd = IMAGECOUNT * type + i;
            CGImageRef imageRef = CGImageCreateWithImageInRect( [image CGImage], CGRectMake(x, y, ITEMIMAGESIZE, ITEMIMAGESIZE)); 
            img = [UIImage imageWithCGImage:imageRef];
            [dict setObject:img forKey:[NSString stringWithFormat:@"%d", loopInd]];
            CGImageRelease(imageRef);
            x += ITEMIMAGESIZE;
        }
    }
    //set image var to be image needed
    image = [dict objectForKey:[NSString stringWithFormat:@"%d", ind]];
  }    

  return image;   
}

有什么建议,从哪里开始?

更新:我在调试区域也有很多消息,都非常相似:

__NSAutoreleaseNoPool(): Object 0x4c55e80 of class NSCFNumber autoreleased with no pool in place - just leaking

__NSAutoreleaseNoPool(): Object 0x4c69060 of class __NSCFDictionary autoreleased with no pool in place - just leaking

__NSAutoreleaseNoPool(): Object 0x4c6a620 of class NSCFString autoreleased with no pool in place - just leaking

__NSAutoreleaseNoPool(): Object 0x4e75fe0 of class NSPathStore2 autoreleased with no pool in place - just leaking

__NSAutoreleaseNoPool(): Object 0x4e312d0 of class UIImage autoreleased with no pool in place - just leaking

2 个答案:

答案 0 :(得分:1)

我发现了问题。在游戏开始时,我正在预加载图像。我有一个方法“loadGameResourses”循环并对单个图像加载方法“loadImageOfType ...”进行多次调用。现在,我正在单独的线程中执行“”loadGameResourses“的调用:

[self performSelectorInBackground:@selector(loadGameResourses) withObject:nil]; 

当我用以下内容替换它时,泄漏就消失了:

[self loadGameResourses];

我听说你需要在主线程中处理UIKit的东西,所以看起来我选择了错误的方法。使用这种适当的方法时,一切都按预期工作:

[self performSelectorOnMainThread: @selector(loadGameResourses) withObject:nil waitUntilDone: NO]; 

答案 1 :(得分:0)

我听说仪器的泄漏工具可以报告漏报。您是否尝试在应用运行并观看内存时打开活动监视器?如果有泄漏,内存量会越来越大。在挖得太深之前,确保你确实有泄漏。