Релиз NSData не восстанавливает память - PullRequest
0 голосов
/ 30 апреля 2010

iPhoneOS 3.2

Я использую unarchiveObjectWithFile из NSKeyedUnarchiver: для загрузки пользовательского объекта, который содержит один большой NSData и другой объект намного меньшего размера. Метод dealloc в моем пользовательском объекте вызывается, объект NSData освобождается, его retainCount == 1 как раз перед этим. Физическая память не уменьшается ни на какую величину, не говоря уже о доле размера NSData, и с помощью предупреждений памяти повторения надежно генерируются: у меня есть тест, пока я фактически не получил предупреждения уровня 2. = (

NSString *archivePath = [[[NSBundle mainBundle] pathForResource:@"lingering"]
     ofType:@"data"] retain];
lingeringDataContainer = [[NSKeyedUnarchiver unarchiveObjectWithFile:archivePath] retain];
[archivePath release];
[lingeringDataContainer release];

а теперь сделка ....

- (void) dealloc {
   [releasingObject release];
   [lingeringData release]; 
   [super dealloc];
}

Перед выпуском:

(gdb) p (int) [(NSData *) lingeringData retainCount]
$ 1 = 1

После того, как:

(gdb) p (int) [(NSData *) lingeringData retainCount]
Цель не отвечает на этот селектор сообщений.

Ответы [ 2 ]

1 голос
/ 30 апреля 2010

Во-первых, вы сохраняете и отпускаете объекты, которые не должны происходить с ними. Вот очищенный код:

NSString *archivePath = [[NSBundle mainBundle] pathForResource:@"lingering"]
     ofType:@"data"]; // Do not retain again.
lingeringDataContainer = [NSKeyedUnarchiver unarchiveObjectWithFile:archivePath]; // Do not retain again.
// Do not release, because archivePath is already autoreleaed: [archivePath release];
// Again, this is already autoreleased: [lingeringDataContainer release];

Или проще:

NSString *archivePath = [[NSBundle mainBundle] pathForResource:@"lingering"]
     ofType:@"data"];
lingeringDataContainer = [NSKeyedUnarchiver unarchiveObjectWithFile:archivePath]; 

Во-вторых, где остальная часть кода? Это, вероятно, что-то еще, что хранится или кэшируется где-то еще.

0 голосов
/ 30 апреля 2010

Когда вы проверяете использование памяти? Это только после фрагмента кода, который вы опубликовали? archivePath и lingeringDataContainer оба автоматически освобождены. Они не будут освобождены до тех пор, пока (по крайней мере) пул авто-релиза не будет слит (обычно в конце текущего события). Также может быть много других внутренних вещей, которые были автоматически освобождены и не исчезнут, пока бассейн не будет слит.

Попробуйте сделать это:

NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; // <==
NSString *archivePath = [[[NSBundle mainBundle] pathForResource:@"lingering"]
 ofType:@"data"] retain];
lingeringDataContainer = [[NSKeyedUnarchiver unarchiveObjectWithFile:archivePath] retain];
[pool release];                                             // <==
[archivePath release];
[lingeringDataContainer release];
...