Почему этот код не протекает? - PullRequest
0 голосов
/ 05 декабря 2010

Я новичок в разработке и не могу понять это:

 for(NSString *collectionName in jsonObjects)
  {
    NSDictionary *collection = [[NSDictionary alloc] init];
    collection = [jsonObjects valueForKey:collectionName];
    NSArray *items = [[NSArray alloc] initWithArray:[collection valueForKey:@"items"]];
    NSNumber *lastAccess = [[NSNumber alloc] init];

    lastAccess = [collection valueForKey:@"lastAccess"];

    [items release];
  }

Я не понимаю, почему, когда я действительно выпускаю lastAccess или коллекция , программа аварийно завершает работу с ошибкой EXC_BAD_ACCESS ..., но если я не выпускаю элементов , я получаю утечку.Может кто-нибудь, пожалуйста, пролить свет на это.Я думал, что если вы используете alloc, то вы владеете ссылкой и поэтому должны выпустить?

Ответы [ 4 ]

4 голосов
/ 05 декабря 2010

Есть много проблем с этим кодом. На данный момент игнорируем, что Фонд кеширует некоторые часто используемые значения.

Этот шаблон не имеет смысла:

NSDictionary *collection = [[NSDictionary alloc] init];
collection = [jsonObjects valueForKey:collectionName];

Первая строка создает (пустой) экземпляр NSDictionary, а вторая строка незамедлительно перезаписывает ссылку на него. И утечка, и совершенно бессмысленная; нет необходимости в присвоении / выделении в первой строке. То же самое касается lastAccess позже.

Поскольку вторая строка возвращает не принадлежащую ссылку, попытка release вызовет сбой.

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

Обратите внимание, что на самом деле вы не увидите утечку экземпляров NSNumber или NSDictionary, потому что в фонде есть их отдельные экземпляры. В случае с NSNumber это просто не имеет смысла. Пустые словари, тем не менее, используются довольно часто, а наличие синглтона экономит память.

1 голос
/ 05 декабря 2010
for(NSString *collectionName in jsonObjects)
{
  NSDictionary *collection = [[NSDictionary alloc] init]; // Allocation 
  collection = [jsonObjects valueForKey:collectionName]; // overwriting above, LEAKS
  NSArray *items = [[NSArray alloc] initWithArray:[collection valueForKey:@"items"]]; // Allocation
  NSNumber *lastAccess = [[NSNumber alloc] init]; // Allocation
  lastAccess = [collection valueForKey:@"lastAccess"]; // overwriting above, LEAKs
  [items release];
}

вызовы, которые не содержат «alloc» или «new», возвращают ссылки на объекты, которые «autoreleased», что означает, что они не принадлежат вам, освобождение их вызовет сбой.Вы можете использовать их, но только в рамках той функции, в которой находитесь, если они понадобятся вам для дальнейшего использования, вам нужно будет вызвать для них retain.Поэтому при вызове функций доступа вам нужно только объявить нужные переменные, а не создавать новые объекты.

alloc создает новый объект, в случае collection вы создаете пустой NSDictionary, но вы быстро перезаписываете ссылку на этот новый объект автоматически выпущенной ссылкой, полученной из valueForKey:, это создаст утечку.Поскольку первоначально созданный объект не будет выпущен.

, вероятно, должен выглядеть следующим образом

for(NSString *collectionName in jsonObjects)
{
  NSDictionary *collection = [jsonObjects valueForKey:collectionName];
  NSArray *items = [collection valueForKey:@"items"];
  NSNumber *lastAccess = [collection valueForKey:@"lastAccess"];
}

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

0 голосов
/ 05 декабря 2010

После @bbum выше, я написал бы ваш код следующим образом:

for(NSString *collectionName in jsonObjects)
{
NSDictionary *collection = [jsonObjects valueForKey:collectionName];
NSArray *items = [NSArray arrayWithObject:[collection valueForKey:@"items"]];
NSNumber * lastAccess = [collection valueForKey:@"lastAccess"];
}

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

0 голосов
/ 05 декабря 2010

В этом коде вы просто переназначаете указатель lastAccess, из-за чего alloc ed NSNumber просачивается.Вам необходимо установить значение для объекта NSNumber, на которое указывает lastAccess.

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

Я поместил пример кода, но я его убираю, так какТеперь я понимаю, что в приведенном выше примере кода слишком много проблем.Посмотрите документацию для NSDictionarycollection вы создаете объект, а затем его утечка, переназначая указатель на что-то другое.После устранения этих проблем я рекомендую обновить вопрос новым кодом.

...