iphonememory-managementcrashquartz-graphicsgdc

Hard crash when drawing content for CALayer using quartz


I am trying to figure out why iOS crash my application in the harsh way (no crash logs, immediate shudown with black screen of death with spinner shown for a while). It happens when I render content for CALayer using Quartz. I suspected the memory issue (happens only when testing on the device), but memory logs, as well as instruments allocation logs looks quite OK. Let me past in the fatal function:

- (void)renderTiles{

    if (rendering) {
        //NSLog(@"====== RENDERING TILES SKIP =======");
        return;
    }
    rendering = YES;



    CGRect b = tileLayer.bounds;
    CGSize s = b.size;
    CGFloat imageScale = [[UIScreen mainScreen] scale];
    s.height *= imageScale;
    s.width *= imageScale;

    dispatch_async(queue, ^{

        NSLog(@"");
         NSLog(@"====== RENDERING TILES START =======");

        NSLog(@"1. Before creating context");
        report_memory();

        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        NSLog(@"2. After creating color space");
        report_memory();

        NSLog(@"3. About to create context with size: %@", NSStringFromCGSize(s));
        CGContextRef ctx = CGBitmapContextCreate(NULL, s.width, s.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);

        NSLog(@"4. After creating context");
        report_memory();

        CGAffineTransform flipTransform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, s.height);
        CGContextConcatCTM(ctx, flipTransform);

        CGRect tileRect = CGRectMake(0, 0, tileImageScaledSize.width, tileImageScaledSize.height);
        CGContextDrawTiledImage(ctx, tileRect, tileCGImageScaled);

        NSLog(@"5. Before creating cgimage from context");
        report_memory();

        CGImageRef cgImage = CGBitmapContextCreateImage(ctx);
        NSLog(@"6. After creating cgimage from context");
        report_memory();

        dispatch_sync(dispatch_get_main_queue(), ^{
            tileLayer.contents = (id)cgImage;        
        });

        NSLog(@"7. After asgning tile layer contents = cgimage");
        report_memory();

        CGColorSpaceRelease(colorSpace);
        CGContextRelease(ctx);
        CGImageRelease(cgImage);

        NSLog(@"8. After releasing image and context context");
        report_memory();


        NSLog(@"====== RENDERING TILES END =======");
        NSLog(@"");
        rendering = NO;

    });
}

Here are the logs:

====== RENDERING TILES START =======
1. Before creating context
    Memory in use (in bytes): 28340224 / 519442432 (5.5%)
2. After creating color space
    Memory in use (in bytes): 28340224 / 519442432 (5.5%)
3. About to create context with size: {6324, 5208}
4. After creating context
    Memory in use (in bytes): 28344320 / 651268096 (4.4%)
5. Before creating cgimage from context
    Memory in use (in bytes): 153649152 / 651333632 (23.6%)
6. After creating cgimage from context
    Memory in use (in bytes): 153649152 / 783159296 (19.6%)
7. After asgning tile layer contents = cgimage
    Memory in use (in bytes): 153653248 / 783253504 (19.6%)
8. After releasing image and context context
     Memory in use (in bytes): 21688320 / 651288576 (3.3%)
====== RENDERING TILES END =======

Application crashes in random places. Sometimes when reaching en of the function and sometime in random step.

Which direction should I look for a solution? Is is possible that GDC is causing the problem? Or maybe the context size or some Core Animation underlying references?


Solution

  • After accurate debugging and experimenting with the rendered context size it turned out to be memory related issue. The solution was to restrict the size of the context to maximum 2048 width and 1024 height