звонок free () работает на симуляторе, злит iPad.iPad разбить - PullRequest
8 голосов
/ 23 июля 2010

Моему приложению не хватает памяти.Чтобы решить эту проблему, я освобождаю два очень больших массива, используемых в функции, которая записывает кадровый буфер в изображение.Метод выглядит следующим образом:

-(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, который я передаю для записи в файл, поврежден, имеет значение null или что-то еще.Но это происходит только тогда, когда я освобождаю эти два буфера.

Я бы понял, была ли память как-то связана с UIIMage, но на самом деле это не должно быть, особенно если это работает на симуляторе.Я задавался вопросом, связано ли это с тем, как iPad обрабатывает «бесплатные» звонки ...

Ответы [ 3 ]

8 голосов
/ 23 июля 2010

Из чтения документов я считаю, что CGDataProviderCreateWithData будет только ссылаться на память, на которую указывает buffer2, а не копировать ее. Вы должны держать его выделенным, пока изображение не будет выпущено.

Попробуйте это:

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 
1 голос
/ 23 июля 2010

Перво-наперво, вы действительно должны проверить, не сработала ли malloc и не вернулась ли NULL. Однако, если это не решит вашу проблему, используйте отладчик и пошагово просмотрите программу, чтобы точно определить, где она выходит из строя (или, по крайней мере, получить трассировку стека). Исходя из моего опыта, странные сбои, такие как сбой где-то в неожиданных областях, почти всегда являются переполнением буфера, повреждающим произвольные данные некоторое время назад.

0 голосов
/ 23 июля 2010

Размер буфера (ов) меньше?Посмотрите на циклы.

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 и x == (768 * 4) -1, индекс buffer2 превышает выделенный размер.Вероятно за пределами диапазона до этого?

...