导致设备内存泄漏的位图

Bitmap causing memory leak on device

我正在使用简单的位图技术将文本转换为图像,然后将此图像划分为光栅,然后计算每个光栅矩形中黑色像素的百分比。在模拟器上一切正常,但在 Device.here 上崩溃是一些相关代码

-(int)blackValue:(UIImage *)image rect:(CGRect)rect {
    int pixelInRect = (int)rect.size.width * rect.size.height;
    __block int blackCount = 0;
    ImageBitmap * imageBitmap = [[ImageBitmap alloc] initWithImage:image  bitmapInfo:(CGBitmapInfo)kCGImageAlphaNoneSkipLast];
    for (int x = 0; x <(int) rect.size.width; x++) {
        for (int y = 0; y < (int) rect.size.height; y++) {
            Byte * pixel = [imageBitmap pixelAtX:(int)rect.origin.x Y:(int)rect.origin.y];
            Byte red = pixel[0];
            if (red <  0.1)
            {
                blackCount++;
            }
        }
    }
    return blackCount/pixelInRect;
}

- (NSDictionary *)rasterizeBitmap:(UIImage *)image size:(CGFloat)size {
    CGFloat width =(int) (image.size.width/size);
    CGFloat height =(int) (image.size.height/size);
    NSMutableArray *fields = [NSMutableArray array];
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            CGRect rect = CGRectMake(x * size, y * size, size, size);
            CGPoint center = CGPointMake(x * size + size/2.0, image.size.height - (y * size + size/2.0));
            double black = [self blackValue:image rect:rect];
            Field * field = [[Field alloc] init];
            field.center = center;
            field.black = black;
            [fields addObject:field];
        }
    }
    return @{@"width":@(width) , @"fields":fields};
}

当我尝试 运行 它在配置文件中时,我得到了以下结果

有人可以建议我如何解决内存问题吗?

问题是您在 ImageBitmap 对象中手动分配内存,但您永远不会释放它。

两个可疑点是位图上下文 (context) 和位图数据 (contextData)。这两个都不是由 ARC 管理的,因此您需要在完成后自行释放它们。

在 ARC 中,您可以简单地在 ImageBitmap class 中实现 dealloc 方法并将清理代码放在那里。

例如:

-(void) dealloc {
    CGContextRelease(context); // releases the bitmap context, if it was created (CGContextRelease checks for NULL)
    free(contextData); // releases the bitmap data (it was explicitly created, so no need to check)
}

同样值得注意的是,您应该使 init 不可用,并标记您指定的初始化程序。

这是因为您 不能 使用您的 imageFromContextpixelAtX:Y: 实例方法,而无需通过自定义 initWithSize:bitmapInfo: 初始化器创建您的实例,因为它创建位图上下文并为位图数据分配内存。

因此,如果您通过调用 init 创建您的实例并调用您的实例方法之一,您很可能会崩溃。

要解决此问题,您可以在 ImageBitmap.h 文件中将 init 方法标记为不可用,并将 initWithSize:bitmapInfo: 方法标记为指定的初始化程序。

-(instancetype) init NS_UNAVAILABLE;

-(id)initWithSize:(CGSize)size bitmapInfo:(CGBitmapInfo)bmInfo NS_DESIGNATED_INITIALIZER;

NS_UNAVAILABLE 所做的只是阻止您通过调用 init 创建您的实例,迫使您使用自定义初始化程序。

如果您尝试执行 [[ImageBitmap alloc] init],编译器将显示以下错误:

NS_DESIGNATED_INITIALIZER 所做的只是确保 ImageBitmap 中的任何额外初始化器必须通过您的初始化器创建新实例,如果不这样做,将向您显示以下警告:

See here for more info on NS_DESIGNATED_INITIALIZER.

现在,实际上这些实际上只是形式,因为您是唯一要使用它的人,并且您知道您必须使用自定义初始化程序。但是,如果您想与其他人共享您的代码,最好办理好这些手续。