【问题标题】:free() call works on simulator, makes iPad angry. iPad smashfree() 调用适用于模拟器,让 iPad 生气。 iPad粉碎
【发布时间】:2011-03-20 01:33:15
【问题描述】:

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

-(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 如何处理“免费”电话...

【问题讨论】:

    标签: iphone c objective-c memory-management free


    【解决方案1】:

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

    【讨论】:

    • 我知道它在哪里失败(有点),但跟踪很长。我现在将其编辑。
    • 你可能是对的溢出。如果我不释放 buffer2,它工作正常。即使我释放缓冲区。
    【解决方案2】:

    通过阅读docs,我相信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

    【讨论】:

    • 我也刚刚意识到这一点!好地方,我的好人。谢谢! :)
    【解决方案3】:

    缓冲区过小?看看循环。

    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 的索引超过了分配的大小。 在此之前可能超出范围?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-27
      • 1970-01-01
      • 1970-01-01
      • 2022-09-24
      相关资源
      最近更新 更多