tags:

views:

60

answers:

2

I had the following code that takes in 14 mb or more of image data encoded in base4 string and converts them to jpeg before writing to a file in iphone. It crashes my program giving the following error : Program received signal: “0”. warning: check_safe_call: could not restore current frame

I tweak my program and it can process a few more images before the error appear again. My coding is as follows:

// parameters is an array where the fourth element contains a list of images in base64 >encoded string 

NSMutableArray *imageStrList = (NSMutableArray*) [parameters objectAtIndex:5]; 
while (imageStrList.count != 0) {   
    NSString *imgString = [imageStrList objectAtIndex:0];  
    // Create a file name using my own Utility class
    NSString *fileName = [Utility generateFileNName];
    NSData *restoredImg = [NSData decodeWebSafeBase64ForString:imgString];
    UIImage *img = [UIImage imageWithData: restoredImg];
    NSData *imgJPEG = UIImageJPEGRepresentation(img, 0.4f); 
   [imgJPEG writeToFile:fileName atomically:YES];
   [imageStrList removeObjectAtIndex:0];
}

I tried playing around with UIImageJPEGRepresentation and found out that the lower the value, the more image it can processed but this should not be the way. I am wondering if there is anyway to free up memory of the imageStrList immediately after processing each image so that it can be used by the next one in the line.

A: 
NSMutableArray *imageStrList = (NSMutableArray*) [parameters objectAtIndex:5]; 
while (imageStrList.count != 0) {
    NSAutoReleasePool *pool = [[NSAutoReleasePool alloc] init];
    NSString *imgString = [imageStrList objectAtIndex:0];  
    // Create a file name using my own Utility class
    NSString *fileName = [Utility generateFileNName];
    NSData *restoredImg = [NSData decodeWebSafeBase64ForString:imgString];
    UIImage *img = [UIImage imageWithData: restoredImg];
    NSData *imgJPEG = UIImageJPEGRepresentation(img, 0.4f); 
   [imgJPEG writeToFile:fileName atomically:YES];
   [imageStrList removeObjectAtIndex:0];
   [pool release];
}

You should create another autoreleasepool inside the loop because objects created inside loop won't be released until the program get out from the loop. Auto release pool inside the loop will release all objects created inside the loop every time.

fish potato
+1  A: 

Your problem is that the UIImages and NSDatas are piling up in memory in a loop. Normally the autorelease pool would take care of this at the end of the event loop, but you're not letting it get that far. You have two choices:

  1. Explicitly allocate/init and then release when done the UIImage and NSData objects, rather than using the +class methods.
  2. Create an explicit autorelease pool inside the loop, and drain it at the end. Do this with:

    NSAutoreleasePool * myPool = [[NSAutoreleasePool alloc] init];

    [myPool release];

quixoto