Могу ли я использовать авто-релиз для устранения этой утечки памяти? - PullRequest
0 голосов
/ 06 июня 2011

У меня утечка памяти в приложении для iPhone.Я добавил Google AdMob в свое приложение, используя образец кода, загруженный из Google.Однако мне было трудно перевести его в режим тестирования, поэтому я добавил дополнительную переменную следующим образом:

GADRequest *r = [[GADRequest alloc] init];
r.testing = YES;
[bannerView_ loadRequest:r];

Я обнаружил утечку памяти с помощью инструментов.Instruments не приводит меня к этой строке кода, он просто выводит меня в файл main.m.Однако, когда я закомментирую код, связанный с AdMob, утечка исчезнет, ​​и я знаю достаточно, чтобы убедиться, что я не позаботился о выпуске этой новой переменной.Я просто не знаю точно, как я должен начать выпускать это.Переменная r не указана в заголовочном файле, так что это весь код, который с ней работает.

Я попытался добавить:

- (void)dealloc {
[r release];
....
}

, но это вызвало ошибку сборки, говорящую "'r' необъявленный ".Это странно, потому что мне кажется, что я объявил r в первой приведенной выше строке, но я думаю, что это неправильно.Любая помощь приветствуется.Я действительно пытался узнать о утечках памяти, но я все еще нахожу их в замешательстве.

Ответы [ 3 ]

4 голосов
/ 06 июня 2011

Просто добавьте [r release];прямо под кодом:

GADRequest *r = [[GADRequest alloc] init];
r.testing = YES;
[bannerView_ loadRequest:r];
[r release];

Переменная r объявлена ​​только в этом разделе вашего кода, поэтому она должна быть освобождена.Смысл освобождения заключается в том, чтобы избавиться от него, как только он вам больше не нужен, поэтому вышеприведенное должно работать идеально для вас.

4 голосов
/ 06 июня 2011

Если ваш r объявлен локально (как кажется, судя по вашему фрагменту), то к нему нельзя получить доступ вне его области (здесь: метод, в котором он был объявлен). Вам также нужно сделать его доступным в вашем экземпляре класса, объявив его иваром.

Объявление этого ивара будет выглядеть так:

@interface YourClass : SuperClass {
    GADRequest *request;
}

//...

@end

Затем вы изменяете свой код на это:

request = [[GADRequest alloc] init];
request.testing = YES;
[bannerView_ loadRequest:request];

Также не забудьте выпустить его в dealloc:

- (void)dealloc {
    [request release];
    //...
}

Однако это , а не , что вы хотите в этой ситуации (я только что включил его, чтобы пояснить, почему вы получаете предупреждение о том, что r не объявляется).

Вам (скорее всего) не понадобится request в любой второй раз после запуска вашего сниппета, таким образом, хранение его в иваре только излишне займет ОЗУ и добавит ненужную сложность вашему классу. Материал, в котором вы нуждаетесь только сразу после его создания, должен быть соответствующим образом обработан (выпущен), что находится в той же области действия.


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

Имейте в виду, что вашему loadRequest: потребуется позаботиться о сохранении r в течение до тех пор, пока это необходимо . Реализация Apple делает это , конечно. Но вы, возможно, захотите написать подобный метод самостоятельно, поэтому помните об этом затем.

GADRequest *r = [[GADRequest alloc] init];
r.testing = YES;
[bannerView_ loadRequest:r];
[r release]; //or: [r autorelease];
0 голосов
/ 07 июня 2011

ОП здесь. Спасибо за все подробные и вдумчивые ответы. Это определенно помогло лучше справиться с управлением памятью. Я сделал именно так, как рекомендовал, добавив [r release] прямо под опубликованным кодом. Тем не менее, у меня все еще есть утечка. Я выделил его на одну строку кода. Следующие утечки:

GADRequest *r = [[GADRequest alloc] init];
r.testing = YES;
[bannerView_ loadRequest:r];
[r release];

Не вытекает следующее:

GADRequest *r = [[GADRequest alloc] init];
r.testing = YES;
// [bannerView_ loadRequest:r];
[r release];

Я полагаю, что я изменяю счетчик сохранения в bannerView с помощью loadRequest, но я не знаю, как это исправить. Я попытался [bannerView_ release] сразу после [r release]; линия (то есть выпуская локально), но это не сработало. Я не ожидал этого, потому что bannerView_ объявлен в другом месте. Я пытался [bannerView_ release]; в методе dealloc, но это не сработало. Я также попытался [bannerView_ autorelease]; на местном уровне. Мудрые головы в Google ставят [bannerView_ release]; в методе ViewDidUnload.

Возможно, инструменты просто запутались в моей голове. Утечка появляется примерно через 10 секунд, но приложение работает хорошо, и объем утечки памяти, по-видимому, не увеличивается по спирали, поскольку приложение продолжает работать. Есть ли такая вещь, как доброкачественная утечка памяти?

Еще раз спасибо за вашу помощь,

Dessie.

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