【问题标题】:What causes this EXC_CRASH in my iPad app?是什么导致我的 iPad 应用程序出现此 EXC_CRASH?
【发布时间】:2011-06-29 09:37:46
【问题描述】:

我从我的 iPad 应用程序的崩溃报告中获得了这个符号化的堆栈跟踪(摘录):

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x00000000, 0x00000000
Crashed Thread:  0

0   ImageIO         0x34528eb4 _CGImagePluginIdentifyPNG + 0
1   ImageIO         0x34528d90 _CGImageSourceBindToPlugin + 368
2   ImageIO         0x34528bda CGImageSourceGetCount + 26
3   UIKit           0x341b8f66 _UIImageRefAtPath + 366
4   UIKit           0x342650ce -[UIImage initWithContentsOfFile:] + 50
5   UIKit           0x342b0314 +[UIImage imageWithContentsOfFile:] + 28
6   DesignScene     0x00013a2a -[LTImageCache fetchImageforURL:] (LTImageCache.m:37)
…

这里是-[LTImageCache fetchImageforURL:]的内容:

- (UIImage *)fetchImageforURL:(NSString *)theUrl {
    NSString *key = theUrl.md5Hash;
    return [UIImage imageWithContentsOfFile:[self filenameForKey:key]];
}

还有-[LTImageCache filenameForKey:]的内容:

- (NSString *) filenameForKey:(NSString *) key {
    return [_cacheDir stringByAppendingPathComponent:key];
}

_cacheDir ivar 在-init 中创建和保留。那么问题来了,是什么导致了这次崩溃?问题是:

  1. -[LTImageCache filenameForKey:] 的返回值需要保留(它是自动释放的)
  2. 某处未处理的异常(+[UIImage imageWithContentsOfFile:] 声称如果图像无法识别,则返回 nil
  3. 还有别的……我猜不到

我认为自动发布的值会很好。事实上,这段代码已经运行了好几个月,而且这个方法在一个会话中被调用了 100 次。这是在非常特殊的情况下很少发生的崩溃(应用程序在一夜之间加载,早上解锁 iPad 时崩溃)。

是什么导致了这个崩溃?

【问题讨论】:

    标签: objective-c cocoa-touch ios memory stack-trace


    【解决方案1】:

    我猜,但它看起来像一个伪造的图像文件。这是在你的 app bundle 中还是你下载的?

    我认为这与内存管理无关。

    为了测试您可以尝试使用 ImageIO 自己打开文件。

      CGImageSourceRef imageSource = CGImageSourceCreateWithURL((CFURLRef)self.url, NULL);
      if(NULL != imageSource) {
        size_t imageCount = CGImageSourceGetCount(imageSource);
        if(imageCount > 0) {
            NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                                       [NSNumber numberWithBool:YES], kCGImageSourceCreateThumbnailFromImageIfAbsent,
                                       [NSNumber numberWithInteger:maxSize], kCGImageSourceThumbnailMaxPixelSize, nil];
            CGImageRef thumbImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, (CFDictionaryRef)options);
            self.image = [UIImage imageWithCGImage:thumbImage scale:scale orientation:imageOrientation];
            CGImageRelease(thumbImage);
            CFRelease(imageSource);
            [pool drain];
        }
      } else {
        NSLog(@"Unable to open image %@", self.url);
      }
    

    然后尝试查找图像计数。

    使用maxSize 并获取缩略图将确保您不会加载 5 兆像素的图像以放入 UI 上的 100x100 磁贴中。

    scale 是窗口的比例(iPhone 4 为 2,其他所有设备为 1)。

    要找到方向,您需要使用CGImageSourceCopyPropertiesAtIndex 函数,然后使用kCGImagePropertyOrientation 键来获取特定图像的方向。

    【讨论】:

    • 文件已下载。 CGImageSource 在 iOS 中吗?文档仅提及 Mac OS X 10.4 或更高版本。无论如何,这只发生在非常特殊的情况下(当应用程序保持打开状态但 iPad 在一夜之间被锁定时)。所以我想知道我是否应该尝试捕获异常并在我得到它时删除文件。这看起来合理吗?
    • 只是跟进,根据我们的 Twitter 对话,这似乎确实是问题所在。我添加了@try/@catch 代码来捕获异常并删除有问题的文件(如果有的话)。感谢您的帮助!
    • 您不能使用@catch 使 EXC_BAD_ACCESS 或 SIGABORT 崩溃。
    猜你喜欢
    • 2021-09-22
    • 2011-06-08
    • 1970-01-01
    • 2011-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-28
    • 1970-01-01
    相关资源
    最近更新 更多