2010-07-19 4 views
0

Мой контроллер получить данные из функции в delegat:утечки памяти в делегатом

- (NSArray *)getChapters { 
NSMutableArray *list = [[NSMutableArray alloc] init]; //memory leak 
    if (chapter_statement == nil) { 
     const char *sql = "SELECT DISTINCT 'Глава '||chapter FROM verses WHERE book=? ORDER by chapter"; 
     if (sqlite3_prepare_v2(database, sql, -1, &chapter_statement, NULL) != SQLITE_OK) { 
      NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database)); 
     } 
    } 

sqlite3_bind_int(chapter_statement, 1, self.book); 
while (sqlite3_step(chapter_statement) == SQLITE_ROW) {     
    NSString *body = [NSString stringWithUTF8String:(char *)sqlite3_column_text(chapter_statement, 0)];  
    [list addObject:body]; 
    [body release]; 
} 

sqlite3_reset(chapter_statement); 
return list; 
} 

и использовать его в контроллере:

- (void)viewWillAppear:(BOOL)animated { 
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 

self.listChapters = [[NSArray alloc] initWithArray:[appDelegate getChapters]]; 

[self.listChapters release]; 

} 

Утечки показывает утечку памяти в: NSMutableArray *list = [[NSMutableArray alloc] init]; Если я вернуться, как return [list autorelease]; сбой приложений в viewWillAppear. Как исправить эту проблему?

ответ

2

Возврат [list autorelease] - правильная вещь. Ваша проблема - [body release], который вам не нужен. - [NSString stringWithUTF8String:] возвращает автореализованный NSString. Явный [body release] означает, что список имеет указатели на освобожденные объекты.

Удалите линию [body release] и положите обратно return [list autorelease], и она должна работать.

Вы также можете запустить статический анализатор (Cmd-shift-A), чтобы попросить компилятор найти другие проблемы с управлением памятью, подобные этой.

+0

Да, это работает, но теперь утечки показывают утечку в - [NSPlaceholderString initWithBytes: length: encoding:] в Foundation –

+0

Я подозреваю, что утечка исходит откуда-то еще. Если вы еще этого не сделали, проверьте FMDB (http: // gusmueller.com/blog/archives/2008/06/new_home_for_fmdb.html) Это базовая оболочка Cocoa для Sqlite, которая может сэкономить вам много горящих вызовов БД. –

0

Рассчитать стоимость!

1.) Вы выделяете массив протекающий здесь:

NSMutableArray *list = [[NSMutableArray alloc] init]; 

retainCount = 1.

2.) Вы добавляете массив в другой массив здесь:

self.listChapters = [[NSArray alloc] initWithArray:[appDelegate getChapters]]; 

Какого новый массив (listChapters) делает ваш утечка массив.

retainCount = 2.

3.) Вы освобождаете массива (listChapters), который содержит протекающую массив:

[self.listChapters release]; 

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

retainCount = 1

+0

Счет за сохранение может быть или не быть абсолютно равным 1 или 2. Никогда не учитывайте абсолютный показатель удержания, всегда учитывайте дельта ... т.е. alloc равен +1, self.listChapters = is +1, -release -1 , – bbum

1

Вы должны autorelease в getChapters, и вы не должны выпускать self.listChapters в viewWillAppear. Это почти никогда не рекомендуется писать [self.something release], потому что тогда вы потенциально освобождаете объект, который вы все еще присвоили этому свойству.

Настоятельно рекомендую вам ознакомиться с memory management rules. Они не длинные или трудные, и как только вы прочитаете и поймете их, вам больше никогда не придется думать о чем-то подобном.

Смежные вопросы