Почему шаблон "Утечка" инструментов не улавливает утечку памяти в моем приложении iOS? - PullRequest
2 голосов
/ 29 июля 2010

Я погружаюсь в разработку под iOS и знакомлюсь с инструментами. В конце каждого дня я выполняю в своем приложении «Запуск с инструментами -> Утечки», чтобы проверить наличие утечек памяти, которые я мог реализовать в тот день. Кажется, редко обнаруживаются какие-либо утечки, и, хотя я хотел бы думать, что я просто естественный программист на iOS, я отказываюсь в это верить;)

Во всяком случае, я только что обнаружил то, что я считаю утечкой памяти в моем коде, и она не обнаруживается инструментами. У меня есть эта строка кода ...

gkSession = [[GKSession alloc] initWithSessionID:@"testID" displayName:@"Temp Display Name" sessionMode:GKSessionModeClient];

и я обнаружил, что не звонил release в моем коде. Мои вопросы ...

  1. Это утечка памяти?
  2. Если да, то по каким причинам инструменты могут его не поймать?

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

Заранее большое спасибо за помощь!

Ответы [ 2 ]

6 голосов
/ 29 июля 2010

Существует несколько типов динамически выделяемой памяти.

  1. Память с числом ссылок больше нуля, на который все еще ссылаются и который используется.

  2. Память с нулевым счетчиком ссылок, на который все еще ссылаются и который еще используется.

  3. Память с счетчиком ссылок больше нуля, на который нет ссылок.

  4. Память с нулевым счетчиком ссылок, на который нет ссылок.

  5. Память с нулевым счетчиком ссылок, на который все еще ссылаются и который НЕ используется.

Тип 1 является нормальной в используемой памяти.Тип два - это ошибка, о которой будет сообщено как о недопустимом доступе, когда вы попытаетесь перейти по ссылке.Тип 3 - это тип утечки, которую обнаруживают приборы.Тип 4 должен быть освобожден системой памяти.

Тип 5 - это утечка, которая не может быть обнаружена приборами, а также не будет обработана полным сборщиком мусора.Это то, что у вас, похоже, есть.

РЕДАКТИРОВАТЬ:

Я забыл тип 6 - Память с подсчетом ссылок, который не соответствует количеству фактических ссылок.Это, вероятно, в конечном итоге превратится в тип 2 или 4.

2 голосов
/ 29 июля 2010

Ответом на вопрос № 1 является «возможно» ... если ваш контроллер представления удален из стека, и никто другой не сохранил его, тогда ваш контроллер представления должен быть освобожден. Но , (и это может быть ответом на ваш вопрос # 2) одна из ошибок, которые я сделал изначально, заключалась в том, что вы не понимали, что при вызове pushViewController: контроллер навигации сохранит ваш контроллер представления, поэтому вы недолжен.Убедитесь, что вы освобождаете свой контроллер вида после того, как создали его и поместили в стек.

MyViewController * viewController = [[MyViewController alloc] init...];
[self.navigationController pushViewController:viewController];
[viewController release];

Я полагаю, что статический анализатор предупредит вас, если вы забудете вызов разблокировки в этой ситуации ... и это одна из причин, по которой статический анализатор так хорош.

Если вы не отпустите контроллер вида в этот момент, ваш счетчик всегда будет на +1 выше, чем должен.

Я заметил, что статический анализатор НАМНОГО более полезен для этих вещей, чем инструмент для обнаружения утечек.(Который, например, не обнаружит «утечку», которая включает в себя циклические ссылки ... два просочившихся объекта, которые ссылаются на себя, не отображаются, потому что «ссылка» все еще существует для вашего объекта).

Таким образом, в настоящее время у вас есть что-то вроде ...

@interface MyClass : UIViewController
{
     GKSession * gkSession;
}

...

@end

в вашей реализации, вы должны убедиться, что вы выпустили свой iVar с помощью метода dealloc:

@implementation MyClass

...

- (void)dealloc
{
     [super dealloc];

     if (gkSession) [gkSession release];
}
@end
...