【问题标题】:Memory leak in CGImageCGImage 中的内存泄漏
【发布时间】:2023-03-24 19:21:01
【问题描述】:

我有一个内存泄漏,我只是不知道如何解决。

这是泄漏代码:

[newImg release];
CGColorSpaceRef d_colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context =  CGBitmapContextCreate(Data, width, 
                                              height, 
                                              8, 4*width, 
                                              d_colorSpace, 
                                              kCGImageAlphaNoneSkipFirst);
UIGraphicsPushContext(context);
CGImageRef new_img = CGBitmapContextCreateImage(context);
UIImage * convertedImage = [[UIImage alloc] initWithCGImage:
                             new_img];
CGImageRelease(new_img);
CGContextRelease(context);
CGColorSpaceRelease(d_colorSpace);
newImg = convertedImage;

我修改存储在 Data 中的像素信息,然后使用此方法从 Data 创建一个 UIImage(作为无符号字符数组)

xcode 工具告诉我这里有泄漏:

CGImageRef new_img = CGBitmapContextCreateImage(context);

这里:

UIImage * convertedImage = [[UIImage alloc] initWithCGImage:
                             new_img];

虽然我释放了他们两个:(有人可以告诉我如何解决这个问题吗?

提前致谢^-^

【问题讨论】:

  • 你在哪里发布convertedImage?还有,为什么你以后用newImg的时候要在最上面放呢?
  • newImg 是一个 istance 属性,因此它可能包含旧图像,这就是我在第一行释放它的原因,因为我用转换后的图像覆盖它。转换后的图像不能被释放,因为它将存储在 newImg 中
  • 你误解了 Objective C 中内存管理的工作原理,你应该只释放你分配的对象。请看我下面的帖子
  • 你永远不会调用 UIGraphicsPopContext()
  • 如果newImg是一个实例属性,比[newImg release];不应该工作,因为它应该是 self.newImg;还是我错了?

标签: iphone ios xcode memory-leaks cgimage


【解决方案1】:

几乎可以肯定,您没有在代码中的其他地方发布newImg。也许您没有在-dealloc 中发布它。如果这是真的,那么 Instruments 将标记分配内存的代码行。它不知道你什么时候应该或不应该释放;它只知道何时分配内存以及何时释放内存。您需要审核您的代码以了解如何管理此 ivar。

也就是说,您正在直接访问您的 ivars,这很糟糕。这是 ObjC 中内存问题的第一大原因。使用属性和访问器(initdealloc 除外),这些问题往往会消失。 (并转换为 ARC。很少有理由再使用手动保留计数,尤其是在 iOS 上。不过,即使使用 ARC,我还是建议使用访问器而不是直接接触您的 ivars。)

另外:请勿致电您的物业newImg。前缀new 在ObjC 中有特殊含义(表示返回的对象应该有一个有效的+1 保留计数)。这可能会导致您出现记忆问题和误报警告。它的名称应该类似于 convertedImagenextImage

【讨论】:

    【解决方案2】:

    编辑:原来的帖子似乎没有帮助,所以删除并重新发布。

    试试这个:

    //[newImg release]; DELETE THIS LINE
    CGColorSpaceRef d_colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context =  CGBitmapContextCreate(Data, width, 
                                                  height, 
                                                  8, 4*width, 
                                                  d_colorSpace, 
                                                  kCGImageAlphaNoneSkipFirst);
    UIGraphicsPushContext(context);
    CGImageRef new_img = CGBitmapContextCreateImage(context);
    
    newImg = [UIImage imageWithCGIImage:new_img];
    
    CGImageRelease(new_img);
    CGContextRelease(context);
    CGColorSpaceRelease(d_colorSpace);
    

    已经对此进行了测试,它并没有在我这边泄漏​​。

    【讨论】:

    • 嗯.. 这不会使 newImg 成为空指针吗?如果你释放convertedImage,因为它是刚刚创建的,我猜一旦你释放它,保留计数就会下降到0,并且由于newImg指向convertedImage,所以当convertedImage被释放时,newImg也是如此,对吧?也许我需要多了解这些点。我来自 Java 编程。:(
    • 我试过那个代码,它实际上导致了一个空指针异常..所以..有人可以帮我吗? :(
    【解决方案3】:

    CGBitmapContextCreate 不会释放你给它的数据。要么给它 NULL(在这种情况下,上下文将管理它自己的后备内存),要么在你释放上下文后自己释放它。

    编辑:here 是相关文档。

    【讨论】:

      【解决方案4】:

      在我看来你没有发布convertedImage尝试替换这一行

      UIImage * convertedImage = [[UIImage alloc] initWithCGImage:
                                   new_img];
      

      这个

      UIImage * convertedImage = [[[UIImage alloc] initWithCGImage:
                                   new_img] autorelease];
      

      在您的代码中。

      如果我对您的理解正确(基于待问的 cmets),您可以像这样声明 newImg 属性:

      @property (nonatomic, retain) UIImage* newImg; //or something like that
      

      在这种情况下,此属性的合成设置器将保留将分配给它的任何对象。并在值发生变化时释放它。 所以你不负责发布它,你应该删除这一行:

      [newImg release];
      

      我想,你能做的最好的事情就是阅读Advanced Memory Management Programming Guide。它不会太长,但它提供了 iOS 内存管理中使用的主要约定的完整概述。

      由于您还使用 CoreFoundation 对象/函数,请考虑使用 Memory Management Programming Guide for Core Foundation

      我希望它会有所帮助:)

      【讨论】:

        猜你喜欢
        • 2014-06-07
        • 2015-02-21
        • 1970-01-01
        • 2012-03-12
        • 1970-01-01
        • 2013-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多