Почему инструменты не обнаруживают эту утечку? - PullRequest
4 голосов
/ 17 апреля 2011

Быстрые люди.Взгляните на фрагмент кода ниже.Я выделяю UILabel * textLabel , но я не выпускаю его (закомментировано).Когда метод заканчивается, я теряю ссылку на указатель, так что он утекает.

Дело в том, что XCode Instruments не обнаруживает эту утечку, и я бы подумал, что найти его довольно просто.Он не сообщает о каких-либо утечках в моем приложении, и все же я нашел это сам, и это вызвало у меня некоторое подозрение.

Я что-то перебираю или инструменты довольно плохо обнаруживают утечки?

-(UITableViewCell*)newReadOnlyCellWithTitle:(NSString*)title andText:(NSString*)text {
    UITableViewCell *cell=[[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];
    cell.textLabel.text=title;
    cell.selectionStyle=UITableViewCellSelectionStyleNone;
    cell.backgroundColor=[UIColor whiteColor];
    cell.opaque=YES;

    UILabel *textLabel=[[UILabel alloc] initWithFrame:CGRectMake(80, 11, 350, 24)];
    textLabel.text=text;
    textLabel.textColor=[UIColor lightTextColor];
    textLabel.font=[UIFont fontWithName:STANDARD_FONT size:16.0];
    textLabel.opaque=YES;
    textLabel.backgroundColor=[UIColor clearColor];
    [cell.contentView addSubview:textLabel];
    //[textLabel release]; //<== without the release this should leak, yep?
    return cell;
}

Редактировать: вывод из статического анализатора ...

enter image description here

Ответы [ 5 ]

4 голосов
/ 18 апреля 2011

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

Instruments не знает расположение или контекст указателя. Если бы вы работали с malloc (1024), и в этом [переработанном] фрагменте памяти оказалось несколько указателей, они бы учитывались, даже если вы никогда не будете снова обращаться с этими указателями как с реальными ссылками.

Итак, нет, утечки никогда не могут быть на 100% точными. Кроме того, существует гораздо больше способов утечки памяти, чем фактическая утечка. Если у вас был глобальный кеш, например:

 NSMutableDictionary *myGlobalCache;

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

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

2 голосов
/ 18 апреля 2011

Позвольте мне угадать, - newReadOnlyCellWithTitle:andText: вызывается вашим -tableView:cellForRowAtIndexPath: методом, когда cell == nil?

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

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

1 голос
/ 18 апреля 2011

Утечки найдут только объекты, на которые не ссылается ни один другой объект. Например, если вы создаете два объекта в методе, которые ссылаются друг на друга, но никто больше не ссылается ни на один из них, они оба являются технически протекающими объектами, но утечки могут видеть их, поскольку у каждого из них есть объект, который ссылается на них. Статический анализатор довольно хорош в обнаружении подобных вещей, хотя эти два в совокупности должны убить почти любую утечку.

1 голос
/ 17 апреля 2011

Я думаю, вы увидите это только тогда, когда нет действительных ссылок.

Итак, в вашем случае все еще есть действительная ссылка, которая выглядит примерно так: (вероятно) Screen -> table -> cell -> label.Похоже, существует вероятность того, что ваш экран, основной вид, все еще находится в памяти, и, следовательно, все еще является действительной ссылкой.

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

0 голосов
/ 17 апреля 2011

Вы пропустили, что есть 2 указателя на объект

Локально у вас есть

UILabel *textLabel=[[UILabel alloc] initWithFrame:CGRectMake(80, 11, 350, 24)];

И в системе управления окнами, которая будет управлять ею для вас (насколько я понимаю, это не копирование, а передача права собственности)

[cell.contentView addSubview:textLabel];

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

//[textLabel release]; //<== without the release this should leak, yep?
...