【问题标题】:How to fix this memory leak while drawing on a UIImage?在 UIImage 上绘图时如何解决此内存泄漏?
【发布时间】:2015-09-15 07:59:22
【问题描述】:

以下问题的附录。

我们已将分配内存的增长跟踪到指向 UIImage 列表的 NSMutableArray。 NSMutable 数组在一个方法中。它没有指向它的外部指针,无论强弱。因为 NSMutableArray 在一个方法中 - 不应该 - 并且它指向的所有对象都会在方法返回后的某个时刻自动取消分配?

我们如何确保发生这种情况?

==================

(1) 首先,调用此代码会导致内存泄漏还是我们应该寻找其他地方?

(在我们看来,这段代码确实会泄漏,因为当我们查看 Apple 的 Instruments 时,运行这段代码似乎会从 CVPixelBuffer 创建一个 1.19MB 的 malloc 字符串 - 跳过代码可以避免这种情况。此外,malloc 分配大小不断在整个执行周期中爬升,似乎永远不会被回收。添加@autorelease 池可以减少峰值内存使用,并有助于延长应用程序的崩溃时间——但基线内存使用量稳步增加,其中最大的罪魁祸首是这些 1.19MB 的 malloc。) image2 是现有的 UIImage。

image2 = [self imageByDrawingCircleOnImage:image2 withX:newX withY:newY withColor:color];

- (UIImage *)imageByDrawingCircleOnImage:(UIImage *)image withX:(int)x withY:(int)y withColor:(UIColor *)color
{
    UIGraphicsBeginImageContext(image.size);
    [image drawAtPoint:CGPointZero];
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [color setStroke];
    CGRect shape = CGRectMake(x-10, y-10, 20, 20);
    shape = CGRectInset(shape, 0, 0);
    CGContextStrokeEllipseInRect(ctx, shape);
    UIImage *retImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return retImage;
}

(2) 其次,如果这段代码确实泄漏了,那么我们如何防止泄漏,更重要的是,当我们快速连续多次调用该方法时,如何防止由于内存不足而导致的崩溃?我们注意到内存使用量激增,因为我们多次调用此方法会导致崩溃。问题是我们如何确保快速释放丢弃的 UIImages,以便应用在多次调用此方法时不会因内存不足而崩溃。

【问题讨论】:

  • 由于此代码不会泄漏,您可能需要查看其他地方,即您在处理图像做什么?
  • @Eiko 你是对的。我们在其他地方发现了泄漏。在下面回答。

标签: ios memory-leaks uiimage


【解决方案1】:

运行此代码似乎会从 CVPixelBuffer 创建一个 1.19MB 的 malloc 字符串

但不要错误地将内存使用称为内存泄漏。仅当使用的内存永远无法回收时,它才是泄漏。你还没有证明这一点。

大量操作使用内存——但是如果操作执行一次就没有关系,因为这样你的代码就会结束并且内存被回收。

只有当您的代码继续运行时才会出现问题,可能会循环,因此永远不会有机会来回收内存;在这种情况下,您可以通过将循环的每次迭代包装在 @autoreleasepool 块中来提供这样的机会。

【讨论】:

    【解决方案2】:

    我们在其他地方发现了泄漏。我们需要释放一个pixelBuffer。我们从 CGI 图像中获取 pixelBuffer 并将缓冲区添加到 AVAssetWriterInputPixelBufferAdaptor - 但它从未被释放。

    在创建缓冲区的这段代码之后:

        CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, 480,
                        640, kCVPixelFormatType_32ARGB, 
                        (__bridge CFDictionaryRef) options, 
                        &pxbuffer);
    

    ...以及将其附加到 AVAssetWriter 的这段代码:

         [adaptor appendPixelBuffer:buffer withPresentationTime:presentTime];
    

    ...我们需要根据SO answer 添加此发布代码:

         CVPixelBufferRelease(buffer);
    

    添加该代码后,应用程序的内存占用保持不变。

    此外,我们在视频编写代码中的多个点添加了@autoreleasepool { } 命令,内存使用峰值趋于平缓,这也稳定了应用程序。

    我们的简单结论是,SO 应该获得诺贝尔奖。

    【讨论】:

    • 是的,方法名称在 Objective-C 中确实应该非常仔细地查看,特别是因为 ARC 使得忘记内存问题变得如此容易。 :)
    猜你喜欢
    • 2020-04-07
    • 1970-01-01
    • 1970-01-01
    • 2015-06-28
    • 1970-01-01
    • 1970-01-01
    • 2014-05-02
    相关资源
    最近更新 更多