8

我的应用程序内存不足。为了解决这个问题,我释放了两个非常大的数组,这些数组用于将帧缓冲区写入图像的函数中。该方法如下所示:

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

注意最后调用 free(buffer) 和 free(buffer2) 的两个?这些在 iPad 模拟器上运行良好,消除了内存问题,让我可以肆无忌惮地生成。但是,他们立即杀死了 iPad。就像,它第一次执行它。如果我删除 free() 调用它运行良好,只是在一两分钟后耗尽内存。那么为什么 free() 调用会导致设备崩溃?

注意 - 明确地使设备崩溃的不是对 free() 的调用,它稍后会崩溃。但这似乎是根本原因/..

编辑 - 有人问它到底在哪里崩溃。此流程继续将图像返回给另一个对象,该对象将其写入文件。当调用 'UIImageJPEGRepresentation' 方法时,它会生成一个 EXT_BAD_ACCESS 消息。我认为这是因为我传递给它以写入文件的 UIImage 已损坏、为空或其他。但这只有在我释放这两个缓冲区时才会发生。

我会理解内存是否与 UIIMage 有某种关联,但实际上不应该如此,尤其是在模拟器上运行时。我想知道这是否取决于 iPad 如何处理“免费”电话......

4

3 回答 3

8

通过阅读文档,我相信 CGDataProviderCreateWithData 只会引用buffer2指向的内存,而不是复制它。您应该一直分配它,直到图像被释放。

试试这个:

静态 void _glToUIImageRelease (void *info, const void *data, size_t size) {
    免费(数据);
}

-(UIImage *)glToUIImage {
    NSInteger myDataLength = 768 * 1024 * 4;
    // 分配数组并将像素读入其中。
    GLubyte *buffer = (GLubyte *) malloc(myDataLength);
    glReadPixels(0, 0, 768, 1024, GL_RGBA, GL_UNSIGNED_BYTE, 缓冲区);

    // gl 呈现“颠倒”,因此从上到下交换到新数组中。
    // 肯定有更好的方法,但这行得通。
    GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
    for(int y = 0; y
于 2010-07-23T12:03:44.010 回答
1

首先,你真的应该检查 malloc 是否失败并返回NULL。但是,如果这不能解决您的问题,请使用调试器并单步执行您的程序以准确查看失败的位置(或至少获取堆栈跟踪)。根据我的经验,奇怪的故障(例如在未预料到的区域中某处崩溃)几乎总是缓冲区溢出破坏了一段时间之前的任意数据。

于 2010-07-23T11:50:15.130 回答
0

缓冲区过小?看看循环。

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

设 y == 0 和 x == (768*4)-1,buffer2 的索引超过了分配的大小。在那之前可能超出范围?

于 2010-07-23T17:32:24.490 回答