free() call works on simulator, makes iPad angry. iPad smash
My app is running out of memory. To resolve this, I free up two very large arrays used in a function that writes a framebuffer to an image. The method looks like this:
-(UIImage *) glToUIImage {
NSInteger myDataLength = 768 * 1024 * 4;
// allocate array and read pixels into it.
GLubyte *buffer = (GLubyte *) malloc(myDataLength);
glReadPixels(0, 0, 768, 1024, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// gl renders "upside down" so swap top to bottom into new array.
// there's gotta be a better way, but this works.
GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
for(int y = 0; y <1024; y++)
{
for(int x = 0; x <768 * 4; x++)
{
buffer2[(1023 - y) * 768 * 4 + x] = buffer[y * 开发者_StackOverflow社区4 * 768 + x];
}
}
// make data provider with data.
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL);
// prep the ingredients
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * 768;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
// make the cgimage
CGImageRef imageRef = CGImageCreate(768, 1024, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
// then make the uiimage from that
UIImage *myImage = [UIImage imageWithCGImage:imageRef];
//free(buffer);
//free(buffer2);
return myImage;
}
Note the two called to free(buffer) and free(buffer2) at the end there? Those work fine on the iPad simulator, removing the memory problem and allowing me to generate with impudence. However, they kill the iPad instantly. Like, the first time it executes it. If I remove the free() calls it runs fine, just runs out of memory after a minute or two. So why is the free() call crashing the device?
Note - it's not the call to free() that explicitly crashes the device, it crashes later. But that seems to be the root cause/..
EDIT - Someone's asked about where it exactly crashes. This flow goes on to return the image to another object, which writes it to a file. When calling the 'UIImageJPEGRepresentation' method, it generates an EXT_BAD_ACCESS message. I assume this is because the UIImage I'm passing it to write to the file is corrupt, null or something else. But this only happens when I free those two buffers.
I'd understand if the memory was somehow related to the UIIMage, but it really shouldn't be, especially as it works on the simulator. I wondered if it is down to how iPad handles 'free' calls...
From reading the docs, I believe CGDataProviderCreateWithData will only reference the memory pointed to by buffer2, not copy it. You should keep it allocated until the image is released.
Try this:
static void _glToUIImageRelease (void *info, const void *data, size_t size) { free(data); } -(UIImage *) glToUIImage { NSInteger myDataLength = 768 * 1024 * 4; // allocate array and read pixels into it. GLubyte *buffer = (GLubyte *) malloc(myDataLength); glReadPixels(0, 0, 768, 1024, GL_RGBA, GL_UNSIGNED_BYTE, buffer); // gl renders "upside down" so swap top to bottom into new array. // there's gotta be a better way, but this works. GLubyte *buffer2 = (GLubyte *) malloc(myDataLength); for(int y = 0; y
First things first, you really should check if malloc failed and returned NULL
. However, if that doesn't solve your problem, use a debugger and step through your programm to see exactly where it fails (or at least to get a stack trace). From my experience, odd failures like crashing somewhere in unsuspected areas almost always are buffer overflows corrupting arbitrary data some time before.
Buffer(s) are undersized? Look at the loops.
for(int y = 0; y <1024; y++)
{
for(int x = 0; x <768 * 4; x++)
{
buffer2[(1023 - y) * 768 * 4 + x] = buffer[y * 4 * 768 + x];
}
}
let y == 0 and x == (768*4)-1, the index of buffer2 exceeds allocated size. Probably outside range before that?
精彩评论