com*_*nda 5 crash jpeg objective-c ios cgimagesource
在我的 iOS 应用程序中,我从 s3 下载游戏资源。我的艺术家更新了一项资产,我们立即开始看到新资产崩溃。
这是处理它们的代码:
+ (UIImage *)imageAtPath:(NSString *)imagePath scaledToSize:(CGSize)size
{
// Create the image source (from path)
CGImageSourceRef imageSource = CGImageSourceCreateWithURL((__bridge CFURLRef) [NSURL fileURLWithPath:imagePath], NULL);
NSParameterAssert(imageSource);
// Get the image dimensions (without loading the image into memory)
CGFloat width = 512.0f, height = 384.0f;
CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL);
NSParameterAssert(imageProperties);
if (imageProperties) {
CFNumberRef widthNumRef = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelWidth);
if (widthNumRef != NULL) {
CFNumberGetValue(widthNumRef, kCFNumberCGFloatType, &width);
}
CFNumberRef heightNumRef = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelHeight);
if (heightNumRef != NULL) {
CFNumberGetValue(heightNumRef, kCFNumberCGFloatType, &height);
}
CFRelease(imageProperties);
} else {
// If the image info is somehow missing, make up some numbers so we don't divide by zero
width = 512;
height = 384;
}
// Create thumbnail options
CGFloat maxDimension = size.height;
if (useDeviceNativeScale) {
maxDimension *= [UIScreen mainScreen].scale;
}
NSParameterAssert(maxDimension);
// If we have a really wide image, scaling it to the screen height will make it too blurry.
// Here we calculate the maximum dimension we want (probably width) to make the image be the full height of the device
CGFloat imageAspectRatio = width / height;
if (width > height) {
maxDimension *= imageAspectRatio;
}
CFDictionaryRef options = (__bridge CFDictionaryRef) @{
(id) kCGImageSourceCreateThumbnailWithTransform : @YES,
(id) kCGImageSourceCreateThumbnailFromImageAlways : @YES,
(id) kCGImageSourceShouldCache : @YES,
(id) kCGImageSourceThumbnailMaxPixelSize : @(maxDimension)
};
// Generate the thumbnail
CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options);
CFRelease(imageSource);
// Crashlytics says the crash is on this line, even though the line above is the one that uses `CFRelease()`
UIImage *image = [UIImage imageWithCGImage:thumbnail];
CGImageRelease(thumbnail);
NSAssert(image.size.height - SCREEN_MIN_LENGTH * [UIScreen mainScreen].scale < 1, @"Image should be the height of the view");
return image;
}
Run Code Online (Sandbox Code Playgroud)
这是来自 Fabric 的 Crashlytics 的堆栈跟踪:
0. 崩溃:com.apple.main-thread
0 核心基础 0x1820072a0 CFRelease + 120
1 荷马 0x10014e7f0 +[UIImage(ResizeBeforeLoading) imageAtPath:scaledToSize:] (UIImage+ResizeBeforeLoading.m:98)
使用此崩溃信息键:
CRASH_INFO_ENTRY_0
* 使用 NULL 调用 CFRelease() *
奇怪的是,这次崩溃并不是 100%,它发生在非常低比例的用户身上。我无法在我自己的任何设备上重现它。它发生在哪个版本的 iOS 上,也没有发生在什么 iOS 硬件上。
这是一个不会导致崩溃的文件:
这是一个确实导致崩溃的文件:
以下是我的生产映像主机(带 cloudfront 的 s3)中它们的链接:
(好) http://d3iq9oupxk0b1m.cloudfront.net/PirateDinosaur/2x/dinoBack._k91G0.jpg
(崩溃) http://d3iq9oupxk0b1m.cloudfront.net/PirateDinosaur/2x/PirateDino.3LHRmc.jpg
即使我使用 Imagemagick 来查看它们,我也看不出它们之间有什么有意义的区别identify -verbose <filename>。有jpeg专家可以指点一下吗?
注意:在我要发布的下一个应用程序版本中,我在释放 NULL 引用方面添加了防护措施,以防止发生此崩溃:
if (imageSource) { CFRelease(imageSource), imageSource = nil; }
...
if (thumbnail) { CGImageRelease(thumbnail), thumbnail = nil; }
Run Code Online (Sandbox Code Playgroud)
然而,我仍然想知道这个 jpeg 到底出了什么问题导致了这次崩溃,以便我的艺术家将来可以避免它。
| 归档时间: |
|
| 查看次数: |
1578 次 |
| 最近记录: |