iphone NSSearchPathForDirectoriesInDomains вызывает утечку памяти?

#iphone #ios #memory #memory-leaks

#iPhone #iOS #память #утечки памяти

Вопрос:

Я новичок в разработке iPhone ObjectiveC. Я получаю утечки памяти, когда запускаю следующий метод.

 - (NSString *) getDBPath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
    NSString *documentsDir = [paths objectAtIndex:0];
    return [documentsDir stringByAppendingPathComponent:@"dbname.sqlite"];
}
  

и я обнаружил, что если я урежу это только до следующего… она все еще протекает

  - (NSString *) getDBPath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
    return nil;
}
  

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

  - (NSString *) getDBPath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
    [paths release];
    return nil;
}
  

Чтобы обнаружить утечку, я запускаю ее в профилировщике со следующим циклом:

 for (int iLoop = 0; iLoop < 30; iLoop  ) {
    NSString *dbPath = [self getDBPath];
    [dbPath release];
    sleep(1);
}
  

Объем памяти, связанный с NSPathStore2 и NSArrayM, продолжает расти.

Любые предложения о том, что я могу делать неправильно? Спасибо!

Комментарии:

1. Что указывает на утечку? Первый метод, который у вас есть, полностью разумен и именно то, что вы должны делать.

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

3. NSZombieEnabled все еще активен? Или нет NSAutoreleasePool, потому что это выполняется в фоновом режиме?

4. У меня нет информации о фактическом профилировании, но повторите свой тест: вам не следует выпускать строку, если вы нигде ее не сохраняете, и пул авторелиза не будет исчерпан до завершения цикла событий. Тем не менее, не уверен, почему вы видите утечку.

5. я думаю, что была бы какая-то другая причина, потому что эти строки не протекают со мной.

Ответ №1:

Ваш код для getDBPath в порядке, но, вероятно, он вызывается из контекста без какого-либо пула авторелиза.

Исправьте это, выделив свой собственный пул в циклическом коде:

 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for (int iLoop = 0; iLoop < 30; iLoop  ) {
    NSString *dbPath = [self getDBPath];
    // [dbPath release]; // do not release! dbPath will be autoreleased
    sleep(1);
}
[pool drain];
  

Ответ №2:

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