Утечки (прибор) сообщает об утечках в автоматически выпущенных объектах

Обновление: эта утечка устранена. Если вы получаете подобные утечки и ваше приложение является многопоточным, вы, скорее всего, делаете вызовы UIKit из фонового потока; использовать, например, [NSThread performSelectorOnMainThread:] для маршрутизации вызовов UIKit к основному потоку, который является единственным местом, где они разрешены.

В последнее время я использовал Leaks в моем текущем проекте, чтобы найти утечки, и я продолжаю сталкиваться с этими «утечками», которые, насколько я могу судить, на самом деле не являются утечками. Согласно Leaks, следующий код, взятый непосредственно из проекта, имеет две утечки:

- (NSArray *)areaForIndex:(int)index 
{
    NSMutableArray *a = [NSMutableArray arrayWithArray:
        [world  retrieveNeighborsForIndex:index]]; // leak 1
    [a insertObject:[references objectAtIndex:index] atIndex:0];
    return [NSArray arrayWithArray:a]; // leak 2
}

Утечка 1 исчезнет, ​​если я изменю первую строку на: (см. Обновление 2-3)

Утечка 2 исчезнет, ​​если я изменю последнюю строку на:

    return a;

К сожалению, я не могу сделать это с утечкой 1, потому что я преобразую неизменяемый массив в изменяемый. Тем не менее, arrayWithArray в любом случае должен автоматически выпускаться, поэтому, насколько я могу судить, он ничего не должен просачиваться. Есть идеи, почему это происходит?

Обновление: я тестировал это как на устройстве, так и на симуляторе. Утечка есть на обоих. Однако на Симуляторе я получаю дополнительную информацию об этой утечке:

История утечки выглядит следующим образом:

# | Category | Event Type  | Timestamp | RefCt |  Address  | Size | Responsible Library | Responsible Caller
--+----------+-------------+
0 | CFArray  | Malloc      | 00:09.598 |     1 | 0x474f6d0 |   48 | asynchro            | -[muddyGrid areaForIndex:]
1 | CFArray  | Autorelease | 00:09.598 |       | 0x474f6d0 |    0 | Foundation          | NSRecordAllocationEvent
2 | CFArray  | CFRetain    | 00:09.598 |     2 | 0x474f7d0 |    0 | Foundation          | -[NSCFArray retain]
3 | CFArray  | CFRelease   | 00:09.611 |     1 | 0x474f7d0 |    0 | Foundation          | NSPopAutoreleasePool

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

Обновление 2 и 3: я попытался изменить строку для утечки 1 на:

    NSMutableArray *a = [[[NSMutableArray alloc] initWithArray:
        [world retrieveNeighborsForIndex:index]] autorelease];

Я думал, что это устранило утечку, но в конечном итоге этого не произошло. Так что я все еще в растерянности.


person Kalle    schedule 28.06.2010    source источник
comment
Вы тестируете на устройстве или симуляторе?   -  person rickharrison    schedule 28.06.2010
comment
На данный момент только на устройстве. Но ты прав, буду тестировать, посмотрю, как все получится, на Симуляторе и обновлю.   -  person Kalle    schedule 29.06.2010
comment
Обновлено описание выше, чтобы включить то, что я понял, попробовав это на симуляторе. Спасибо за указатель! :)   -  person Kalle    schedule 29.06.2010


Ответы (3)


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

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

person Kalle    schedule 16.07.2010

Что retrieveNeighborsForIndex возвращается?

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

person Michael Kessler    schedule 28.06.2010
comment
Он возвращает [соседи allObjects], где соседи - это NSMutableSet, содержащий несколько объектов (9-12). - person Kalle; 29.06.2010

arrayWithArray сохраняет объекты, которые вы сохранили в своем изменяемом массиве. http://www.iphonedevsdk.com/forum/iphone-sdk-development/14285-nsmutablearray-arraywitharray-does-add-retain.html

Я бы порекомендовал выпустить его или еще безопаснее создать объекты с установленным атрибутом autorelease. При вызове извлечения соседей для индекса сделайте эти объекты автоматически освобожденными, и они будут освобождены, когда массив nsmutable будет освобожден

РЕДАКТИРОВАТЬ: Один совет, который я мог бы добавить при отслеживании ошибок памяти, - это включить зомби и проверить счетчик ссылок ваших объектов. Затем вы можете определить, какие из них не выпускаются, и это должно упростить отслеживание. Эта ссылка покажет вам, как настроить ваш проект xcode для включения зомби: cocoadev.com/index.pl?NSZombieEnabled

person Kaili    schedule 28.06.2010
comment
Это так, но массив, возвращаемый arrayWithArray:, сам выпускается автоматически, поэтому его самостоятельное освобождение, вероятно, вызовет сбой. Тем не менее, вероятно, безопасно возвращать сам изменяемый массив, поскольку вы создаете его и возвращаете тем же методом, без скрытых побочных эффектов. - person Wevah; 29.06.2010
comment
Это работает для утечки 2 (и это то, что я делаю сейчас), но не устраняет утечку 1, где я беру неизменный массив в изменяемый массив с помощью arrayWithArray, поскольку мне нужно добавить к нему, прежде чем возвращать его . - person Kalle; 29.06.2010
comment
Между прочим, я ответил Wevah; Право Тени в том, что arrayWithArray: сохраняет объекты в массиве, но сам он не содержится и не должен выпускаться или автоматически выпускаться. - person Kalle; 29.06.2010
comment
Ваш неизменяемый массив не находится в пуле автозапуска. Попробуйте добавить в этот массив атрибут autorelease - person Kaili; 29.06.2010
comment
Тень: возможно, мне что-то не хватает, но это нигде не сохраняется (возвращается как автоматически выпущенный объект) - [NSSet allObjects] не возвращает сохраненный объект. - person Kalle; 29.06.2010
comment
Когда вещи добавляются в NSSet, они получают Retain. Просто убедитесь, что вы убрали свой беспорядок, когда закончите. Какао и его модель памяти разочаровывают. Самое главное, что стоит проверить, - это различные методы, которые создают массивы ваших объектов. Если эти свойства увеличивают счетчик ссылок ваших объектов, это одна из причин утечки памяти. (Предполагается, что объекты, которые добавляются в ваш NSSet, любой массив, НЕ являются автоматически выпущенными объектами) - person Kaili; 29.06.2010
comment
Также запускайте с включенными зомби и проверяйте количество ссылок ваших объектов. Затем вы можете определить, какие из них не выпускаются, и это должно упростить отслеживание. cocoadev.com/index.pl?NSZombieEnabled Должно помочь вам включить это. - person Kaili; 29.06.2010
comment
Shadow: большое спасибо за все ваши комментарии. Я пробовал зомби, и в этом конкретном случае я имею дело исключительно с автоматически выпущенными объектами, но я трижды проверю счетчики сохраненных данных и тому подобное и прокомментирую позже сегодня. :) - person Kalle; 30.06.2010