简体   繁体   English

free()调用适用于模拟器,让iPad生气。 iPad粉碎

[英]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 * 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? 注意两个在那里调用free(缓冲区)和free(buffer2)吗? Those work fine on the iPad simulator, removing the memory problem and allowing me to generate with impudence. 这些在iPad模拟器上工作正常,消除了内存问题,让我产生了无礼。 However, they kill the iPad instantly. 然而,他们立刻杀了iPad。 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. 如果我删除free()调用它运行正常,一两分钟后就会耗尽内存。 So why is the free() call crashing the device? 那么为什么free()调用会使设备崩溃?

Note - it's not the call to free() that explicitly crashes the device, it crashes later. 注意 - 这不是对free()的调用,它明确地崩溃了设备,它会在以后崩溃。 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. 调用'UIImageJPEGRepresentation'方法时,它会生成EXT_BAD_ACCESS消息。 I assume this is because the UIImage I'm passing it to write to the file is corrupt, null or something else. 我假设这是因为我传递它写入文件的UIImage是损坏的,null或其他东西。 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. 我知道内存是否与UIIMage有某种关系,但它确实不应该,特别是因为它在模拟器上工作。 I wondered if it is down to how iPad handles 'free' calls... 我想知道iPad是如何处理“免费”通话的?

From reading the docs , I believe CGDataProviderCreateWithData will only reference the memory pointed to by buffer2, not copy it. 从阅读文档 ,我相信CGDataProviderCreateWithData只会引用 buffer2指向的内存,而不是复制它。 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 . 首先,你应该检查malloc是否失败并返回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. 令y == 0和x ==(768 * 4)-1,buffer2的索引超过分配的大小。 Probably outside range before that? 可能在之前的范围之外?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM