如何在 UIImage 上绘制时修复此内存泄漏?
How to fix this memory leak while drawing on a UIImage?
下面问题的附录。
我们已将分配内存的增长追踪到指向 UIImage 列表的 NSMutableArray。 NSMutable 数组在一个方法中。它没有指向它的外部指针,无论强弱。因为 NSMutableArray 在方法中 - 不应该 - 并且它指向的所有对象都会在方法 returns?
之后的某个时间点自动取消分配
我们如何确保发生这种情况?
=================
(1) 首先,调用此代码是否会导致内存泄漏,还是我们应该寻找其他地方?
(在我们看来,当我们查看 Apple 的 Instruments 时,这段代码确实会泄漏,运行 这段代码似乎从 CVPixelBuffer 创建了一个 1.19MB 的 malloc 字符串——跳过代码可以避免这种情况。另外, malloc 分配大小在执行周期中不断攀升并且似乎永远不会被回收。添加 @autorelease 池减少了峰值内存使用并帮助延长了应用程序崩溃的时间 - 但基线内存使用稳步增加,最大的罪魁祸首是这些 1.19MB mallocs。)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,使应用程序在多次调用此方法时不会因内存不足而崩溃。
running this code seems to create a string of 1.19MB mallocs from CVPixelBuffer
但是不要犯调用内存使用内存泄漏的错误。只有当使用过的内存永远无法回收时,这才是泄漏。你还没有证明。
很多操作使用内存——但如果操作只执行一次就没关系了,因为那样你的代码就结束了,内存也被回收了。
只有当您的代码继续运行时才会出现问题,可能会循环,因此永远不会 有机会 回收内存;在这种情况下,您可以通过将循环的每次迭代包装在 @autoreleasepool
块中来提供这样的机会。
我们在其他地方发现了泄漏。我们需要释放一个 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 应该获得诺贝尔奖。
下面问题的附录。
我们已将分配内存的增长追踪到指向 UIImage 列表的 NSMutableArray。 NSMutable 数组在一个方法中。它没有指向它的外部指针,无论强弱。因为 NSMutableArray 在方法中 - 不应该 - 并且它指向的所有对象都会在方法 returns?
之后的某个时间点自动取消分配我们如何确保发生这种情况?
=================
(1) 首先,调用此代码是否会导致内存泄漏,还是我们应该寻找其他地方?
(在我们看来,当我们查看 Apple 的 Instruments 时,这段代码确实会泄漏,运行 这段代码似乎从 CVPixelBuffer 创建了一个 1.19MB 的 malloc 字符串——跳过代码可以避免这种情况。另外, malloc 分配大小在执行周期中不断攀升并且似乎永远不会被回收。添加 @autorelease 池减少了峰值内存使用并帮助延长了应用程序崩溃的时间 - 但基线内存使用稳步增加,最大的罪魁祸首是这些 1.19MB mallocs。)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,使应用程序在多次调用此方法时不会因内存不足而崩溃。
running this code seems to create a string of 1.19MB mallocs from CVPixelBuffer
但是不要犯调用内存使用内存泄漏的错误。只有当使用过的内存永远无法回收时,这才是泄漏。你还没有证明。
很多操作使用内存——但如果操作只执行一次就没关系了,因为那样你的代码就结束了,内存也被回收了。
只有当您的代码继续运行时才会出现问题,可能会循环,因此永远不会 有机会 回收内存;在这种情况下,您可以通过将循环的每次迭代包装在 @autoreleasepool
块中来提供这样的机会。
我们在其他地方发现了泄漏。我们需要释放一个 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 应该获得诺贝尔奖。