theory
theory

Reputation: 9887

What causes this EXC_CRASH in my iPad app?

I got this symbolicated stack trace from a crash report from my iPad app (excerpt):

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)
…

Here are the contents of -[LTImageCache fetchImageforURL:]:

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

And the contents of -[LTImageCache filenameForKey:]:

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

The _cacheDir ivar is created and retained in -init. So the question is, what caused this crash? Is the problem that:

  1. the return value of -[LTImageCache filenameForKey:] needs to be retained (it's autoreleased)
  2. An unhandled exception somewhere (+[UIImage imageWithContentsOfFile:] claims to return nil if the image is unrecognizable)
  3. Something else…I'm out of guesses

I would think that an autoreleased value would be fine. An in truth, this code has been working fine for months, and this method is called 100s of times in a session. This is a rare crash under very specific circumstances (the app left loaded overnight, crash upon unlocking the iPad in the morning).

What's causing this crash?

Upvotes: 1

Views: 818

Answers (1)

Bill Dudney
Bill Dudney

Reputation: 3358

I'm guessing but it looks like a bogus image file. Is this in your app bundle or do you download it?

I don't think it has anything to do with memory mgt.

To test you could try using ImageIO to open the file yourself.

  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);
  }

and then try to find the image count.

Using maxSize and getting a thumbnail will ensure you don't load a 5 mega-pixel image to put into a 100x100 tile on your UI.

scale is the window's scale (will be 2 for iPhone 4 and 1 for everything else).

To find the orientation you need to use the CGImageSourceCopyPropertiesAtIndex function and then the kCGImagePropertyOrientation key to get the orientation of the particular image.

Upvotes: 1

Related Questions