Моя выделенная память записывается в - PullRequest
0 голосов
/ 01 сентября 2010

Я пишу проект в Objective-C, но в значительной степени полагаюсь на старый добрый C, поскольку в нем задействован OpenGL.

У меня есть блок данных, который я считываю в память из файла следующим образом:

NSString *path = [[NSBundle mainBundle] pathForResource:@"iPadTest" ofType:@""];
NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path];
data = [file readDataToEndOfFile];
currentImage = [ReadDataFiles getOrganizedImageData:data];

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

ImageData *organizedImageData = malloc(sizeof(ImageData));

// IMAGE DIMENSIONS
UInt64 *rawData = (UInt64 *) data.bytes;
organizedImageData->imageDimensions.x = *rawData;
rawData++;
organizedImageData->imageDimensions.y = *rawData;
rawData++;
organizedImageData->imageDimensions.z = *rawData;

// IMAGE 1
rawData++;
organizedImageData->image1Data = (UInt8*)rawData;
// IMAGE 2
rawData++;
organizedImageData->image2Data = (UInt8*)rawData;

// etc...

Проблема в том, что когда данные достигают функций OpenGL, что-то еще записывается в ту же память.Результат каждый раз разный, но данные никогда не бывают постоянными.

Когда я говорю отладчику сделать паузу, когда эти адреса меняются, я в конечном итоге получаю код сборки, из которого я ничего не могу сделать.

Как и где я должен распределить пространство памяти, чтобы остальная часть программы не дурачилась с ним?

Ответы [ 2 ]

2 голосов
/ 01 сентября 2010

Проблема заключается в том, что вы не являетесь владельцем переменной, называемой данными, и она почти наверняка освобождается при первом обращении к стоку автозапуска (или, если вы используете GC, она исчезает после того, как выходит из области видимости).Когда data уходит, все те указатели, которые вы тщательно создаете, чтобы указать на [data bytes], остаются висящими.

В среде с подсчетом ссылок вам необходимо отправить -retain на data до того, как пул автоматического выпуска (что гарантированно произойдет, когда вы вернетесь в цикл выполнения), а затем вам нужно освободить егокогда вы закончите с данными в нем.В среде GC вам просто необходимо сохранить надежную ссылку, например, сделать ее иваром какого-либо объекта.

В качестве альтернативы, вы можете скопировать данные в другое место, вместо того, чтобы просто создавать указатели на их биты.

0 голосов
/ 01 сентября 2010

Извините, я не могу оставлять комментарии, поэтому вот полный ответ:
Как сказал Джереми, у вас нет ссылки на data, поэтому она исчезнет!

Однако есть несколько способов обеспечить его жизнеспособность:

  1. Храните data (и я действительно имею в виду указатель здесь!) В своей структуре, чтобы вы могли освободить его, когда закончите с его использованием.
    Если вы работаете в GC, определите это поле как __strong void * или (так как NSData является бесплатным для CFData), вызовите CFRetain( (CFDataRef) data ), который на самом деле не a noop в коде GC-ed ! (Это относится к средам GC-ed и с пересчетом BTW ...)
  2. Создайте этот объект через [[NSData alloc] initWithContentsOfFile:] и сохраните его в своей структуре. (GC-заметки применимы и здесь!)
  3. malloc памяти для вашего изображения и используйте -[NSData getBytes:range:] с этим.
    Это, вероятно, будет означать заметное снижение производительности.

Какой бы способ вы ни выбрали, не забывайте убирать за собой - CFRelease(), вероятно, будет самым хорошим решением в случаях 1 и 2, поскольку он охватывает GC и пересчет.


Кстати (и я надеюсь, это не прозвучит как грубость!):
Есть ли определенная причина, по которой ...

  1. вы используете NSFileHandle вместо прямого NSData -метода?
  2. у вас есть данные в виде блоба?
    Вы можете сохранить его как бинарный список с помощью NSKeyedArchiver и получить его немного более элегантно, чем с помощью гимнастики указателя, но с небольшими накладными расходами.

Да, и большой:
Что точно вы делаете / пытаетесь сделать здесь:

// IMAGE 1
organizedImageData->image1Data = (UInt8 *)rawData;
rawData++;
// IMAGE 2
organizedImageData->image2Data = (UInt8 *)rawData;
rawData++;

Я не могу понять этого.
Предложение 2, вероятно, также упростит это, кстати: -)

...