【问题标题】:GPUImage allocation not releasing with ARC enabled projectGPUImage 分配未与启用 ARC 的项目一起释放
【发布时间】:2017-05-12 17:25:11
【问题描述】:

我正在连续拍摄多张照片并使用 GPUImage 框架对其进行处理。我有一个辅助类,主要用于执行 GPUImageSubtractBlendFilter。这是我的工作:

#import "ImageProcessor.h"

@interface ImageProcessor ()

@end

@implementation ImageProcessor

GPUImageSubtractBlendFilter *subFilter;

-(id)init {
    self = [super init];
    subFilter = [[GPUImageSubtractBlendFilter alloc] init];
    return self;
}

-(UIImage*)flashSubtract:(UIImage*) image1 : (UIImage*) image2{
    UIImage *processedImage;
//    @autoreleasepool {

    //CAUSING MEMORY ISSUE
    GPUImagePicture *img1 = [[GPUImagePicture alloc] initWithImage:image1];
    GPUImagePicture *img2 = [[GPUImagePicture alloc] initWithImage:image2];
    //MEMORY ISSUE END

    [img1 addTarget:subFilter];
    [img2 addTarget:subFilter];

    [img1 processImage];
    [img2 processImage];
    [subFilter useNextFrameForImageCapture];
    processedImage = [subFilter imageFromCurrentFramebuffer];

//    }

    //consider modifications to filter possibly?


    return processedImage;
}

内存不断增长,即使启用 ARC 也不会释放。我对其进行了调试并将其缩小到这两个分配的核心:

 img1 = [[GPUImagePicture alloc] initWithImage:[imagesArray objectAtIndex:1]];
 img2 = [[GPUImagePicture alloc] initWithImage:[imagesArray objectAtIndex:0]];

我在这里遗漏了什么,或者我应该做些什么更好地不连续分配 GPUImagePicture 变量?

这里是代码的来源:

-(void)burstModeCapture : (AVCaptureConnection *) videoConnection : (int) i{//start capturing picture s rapidly and cache them in ram

    dispatch_group_t group = dispatch_group_create();
    dispatch_group_enter(group);

    NSLog(@"time entering: %d", i);


    [photoOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageSampleBuffer, NSError *error)
     {

         if(error)
             NSLog(@"%s",[[error localizedDescription] UTF8String]);

         CVImageBufferRef cameraFrame = CMSampleBufferGetImageBuffer(imageSampleBuffer);
         CVPixelBufferLockBaseAddress(cameraFrame, 0);
         Byte *rawImageBytes = CVPixelBufferGetBaseAddress(cameraFrame);
         size_t bytesPerRow = CVPixelBufferGetBytesPerRow(cameraFrame);
         size_t width = CVPixelBufferGetWidth(cameraFrame);
         size_t height = CVPixelBufferGetHeight(cameraFrame);
         NSData *dataForRawBytes = [NSData dataWithBytes:rawImageBytes length:bytesPerRow * CVPixelBufferGetHeight(cameraFrame)];
         // Do whatever with your bytes

         // create suitable color space
         CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

         //Create suitable context (suitable for camera output setting kCVPixelFormatType_32BGRA)
         CGContextRef newContext = CGBitmapContextCreate(rawImageBytes, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);

         CVPixelBufferUnlockBaseAddress(cameraFrame, 0);

         // release color space
         CGColorSpaceRelease(colorSpace);

         //Create a CGImageRef from the CVImageBufferRef
         CGImageRef newImage = CGBitmapContextCreateImage(newContext);
         UIImage *FinalImage = [[UIImage alloc] initWithCGImage:newImage];
         [imagesArray addObject:FinalImage];//append image to array


         dispatch_group_leave(group);
     }];

    dispatch_group_notify(group, dispatch_get_main_queue(), ^{//execute function recursively to shoot n photos
        //base case to stop shooting pictures
        shootCounter--;

        if (shootCounter <= 0) {
            [flash turnOffFlash];
            shootCounter = NUMSHOTS;
            UIImage *output = [self processImages]; //THIS IS WHERE MEMORY STARTS ACCUMULATING
            [self updateUIWithOutput:output];
            NSLog(@"Done shooting!");
        }
        else {
            [NSThread sleepForTimeInterval: 0.1];
            [self burstModeCapture:videoConnection : shootCounter];
        }
    });


}

我递归地运行此函数两​​次以捕获图像对。 [imageProcessor flashSubtract] 是问题所在。

【问题讨论】:

  • 有什么理由GPUImagePicture *img1GPUImagePicture *img2 在你的flashSubtract: 方法中不是局部变量吗?如果您在其他地方需要它们,您应该将它们定义为类属性。我不是说它会解决你的问题,但肯定不会伤害。
  • 它们最初是局部变量,我试着让它们成为全局变量,以为这可以解决它。但什么都没有改变。
  • 您的可变数组也将保存对对象的引用,因此如果您继续向其中添加对象并且它的大小不断增长,您将使用越来越多的内存。顺便说一句,将可变数组作为参数传递不是一个好习惯,传递非可变副本要安全得多。
  • 我只在该数组中存储两个值,并在每对图片完成处理后执行[imagesArray removeAllObjects]。我将代码更改为获取图像的两个副本并使用它们,在分配 GPUImagePicture 的这两行之后,内存使用量仍然不断增加。
  • 那么为什么不创建一个使用 2 个参数而不是使用 NSMutableArray 的方法呢?

标签: ios objective-c automatic-ref-counting gpuimage


【解决方案1】:

您在CGImageRef newImage = CGBitmapContextCreateImage(newContext); 行之后缺少CGContextRelease(newContext);。这可能会导致您的内存泄漏。

【讨论】:

  • 我试过了,不幸的是它没有用。当我单步执行代码时,我前面提到的两行代码突然增加了内存使用量。
  • 我正在传递这样的图像:UIImage *processedImage = [imageProcessor flashSubtract:[imagesArray objectAtIndex:1] : [imagesArray objectAtIndex:0]]; 这可能是一个引用问题吗?
  • 它应该不会导致问题,但是使用临时变量是一个超级快速的检查方法。值得一试。
  • 非常感谢,我想通了!我运行了构建分析器并意识到我没有释放我的 CGImageRef 对象(newImage)。您对内存泄漏的一般区域是正确的!
  • 另一个 bug 尘埃落定 ;-) 恭喜,编码愉快
猜你喜欢
  • 2012-10-19
  • 1970-01-01
  • 2012-02-28
  • 2012-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-11
  • 2019-07-08
相关资源
最近更新 更多