Im Stumped, Почему память UIImage \ Texture2d не освобождается - PullRequest
0 голосов
/ 04 мая 2010

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

Я настроил этот базовый тест, чтобы попытаться найти причину, по которой моя память не освобождалась:

if (texture != nil)
{
[texture release];
texture = nil;
}
else
{
UIImage* ui = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"image" ofType:@"png"]];
texture = [[Texture2D alloc] initWithImage:ui];
}

Теперь я бы поместил это в начало касаний и проверил, наблюдая за использованием памяти с помощью insttruments в начале (обычно 11,5 - 12 Мб). после первого касания, при отсутствии объекта, создается текстура, и память переходит на 13,5 - 14

Однако после второго касания память уменьшается, но только до 12,5 - 13 *. 1008 *

Заметный кусок памяти все еще занят.

Я проверил это в гораздо большем масштабе, загружая 10 таких больших текстур за раз Память перепрыгивает до 30 мб и остается там, но при втором касании после освобождения текстур она падает только до 22 мб.

Я пытался выполнить тест в другой раз, загружая изображения с помощью [uiimage imagenamed:], но из-за кеширования этот метод выполняет только то, что в памяти остаются полные 30 МБ.

Ответы [ 2 ]

0 голосов
/ 05 мая 2010

Кажется, я нашел проблему. Я не совсем понимаю, почему это происходит, но, кажется, когда я запускаю инструменты для контроля использования памяти, если я одновременно отслеживаю активность ввода-вывода (это инструмент по умолчанию, который изначально загружен в) показанное использование памяти ОЧЕНЬ больше (более чем в 3 раза) и остается в памяти даже после освобождения объектов. Я предполагаю, что это из-за накладных расходов на мониторинг активности ввода-вывода.

Во всяком случае, когда я отключаю это, использование памяти первоначально составляет 3,16 МБ (намного лучше), при загрузке 10 огромных текстур оно увеличивается до 10 МБ, а после выгрузки текстуры возвращается обратно к 3.16. Блестящий результат.

0 голосов
/ 04 мая 2010

В вашем коде есть только одно место (из того, что мы видим), где текстура может быть освобождена, и это в выражении [texture release];.

Вам нужно выполнить это утверждение (или другое где-то еще). Вы проверяли, что для каждой выделенной текстуры вы также освобождаете ее? Вы можете добавить операторы NSLog, чтобы помочь, например так:

if (texture != nil) {
    NSLog("releasing texture instance: %08x", texture);
    [texture release];
    texture = nil;
} else {
    ...
    texture = [[Texture2D alloc] initWithImage:ui];
    NSLog("allocated texture instance: %08x", texture);
}

Возможно, текстура сохраняется где-то еще? Например, вы добавляете его в подпредставление или в массив или словарь? Те сохраняют свое содержание.

В качестве последнего средства для действительно сложной проблемы отслеживания выделения / выпуска я переопределил методы retain, release, dealloc, чтобы убедиться, что они вызываются, когда я ожидаю. Это может быть излишним в данный момент, но вот как: я добавил int myRetainCount; ivar, чтобы помочь мне отслеживать:

-(void)release {
    NSLog(@"release %08x %2d -> %2d (%u)", 
          self, myRetainCount, myRetainCount-1, self.retainCount);
    myRetainCount--;
    [super release];
}

-(id)retain {
    NSLog(@"retain  %08x %2d -> %2d (%u)", 
          self, myRetainCount, myRetainCount+1, self.retainCount);
    myRetainCount++;
    return [super retain];
}

- (void)dealloc {
    NSLog(@"dealloc %08x %2d       (%u)", self, myRetainCount, self.retainCount);

    // deallocate self's ivars here...

    [super dealloc];
}
...