IOS - 生成本地映像的MD5时内存耗尽

时间:2016-10-14 13:56:56

标签: ios swift crash photosframework

我正在使用应用程序从用户Camera Roll上传照片。作为上传的一部分,我需要计算照片的MD5(在上传之前检查重复项)。目前,由于malloc错误,应用程序经常崩溃。

为了追踪问题,我创建了一个简单的测试程序,它只生成设备上所有照片的MD5,并且该程序以相同的方式崩溃。

我使用的代码如下:

class ViewController: UIViewController {

@IBOutlet weak var numberOfPhotos: UILabel!
let imageManager = PHImageManager.default()
lazy var imageRequestOptions : PHImageRequestOptions = {
    var options = PHImageRequestOptions()
    options.isSynchronous = false
    options.deliveryMode = .highQualityFormat
    return options
}()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    let collection = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .smartAlbumUserLibrary, options: nil).firstObject
    let options = PHFetchOptions()
    options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.image.rawValue)

    let allImages = PHAsset.fetchAssets(in: collection!, options: options)


    allImages.enumerateObjects({
        asset, index, stop in
        self.imageManager.requestImageData(for: asset , options: self.imageRequestOptions, resultHandler: {
            imageData,dataUTI,orientation,info in
            if imageData != nil {
                    let digestLength = Int(CC_MD5_DIGEST_LENGTH)
                    var md5Buffer = [UInt8](repeating: 0, count: digestLength)

                    let _ = imageData!.withUnsafeBytes { (body: UnsafePointer<UInt8>) in
                        CC_MD5(body, CC_LONG(imageData!.count), &md5Buffer)
                    }

            }
        })

    })


}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

此程序将在失败前处理大约50张照片,并出现以下错误:

2016-10-14 15:51:41.565468 PhotoLoadTest[3513:804150] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** NSAllocateMemoryPages(7679134) failed'
*** First throw call stack:
(0x1910101c0 0x18fa4855c 0x191010108 0x191a6265c 0x191a38ac8 0x191a03404 0x100720fa8 0x1006c31f8 0x100015a38 0x19c77e930 0x10098525c 0x10098521c 0x10098a284 0x190fbdf2c 0x190fbbb18 0x190eea048 0x19296d198 0x196ec3818 0x196ebe550 0x100017ca8 0x18fecc5b8)
libc++abi.dylib: terminating with uncaught exception of type NSException

通过Instruments运行程序时,我发现在程序崩溃之前,持久性内存使用率攀升至1.6 GB。

如果我注释掉CC_MD5的电话,该程序运行正常......

我不会立即看到此程序泄漏内存的位置。你知道为什么会崩溃吗?

1 个答案:

答案 0 :(得分:0)

autoreleasepool{
allImages.enumerateObjects({
        asset, index, stop in
        self.imageManager.requestImageData(for: asset , options: self.imageRequestOptions, resultHandler: {
            imageData,dataUTI,orientation,info in
            if imageData != nil {
                    let digestLength = Int(CC_MD5_DIGEST_LENGTH)
                    var md5Buffer = [UInt8](repeating: 0, count: digestLength)

                    let _ = imageData!.withUnsafeBytes { (body: UnsafePointer<UInt8>) in
                        CC_MD5(body, CC_LONG(imageData!.count), &md5Buffer)
                    }

            }
        })

    })

}

上面的代码可能会工作,因为您正在遍历所有图像自动释放池将负责内存管理。