2010-07-19 69 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:]在基金会 – 2010-07-20 17:52:50

+0

我怀疑泄漏来自其他地方。如果您还没有,请查看FMDB(http:// gusmueller。com/blog/archives/2008/06/new_home_for_fmdb.html)这是一个Sqlite的基本Cocoa包装器,可以为您节省很多管理数据库调用的麻烦。 – 2010-07-21 05:42:45

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 2010-07-19 23:47:55

1

你应该自动释放在getChapters,你不应该在viewWillAppear释放self.listChapters。这是写一个[self.something release]从来没有好主意,因为那么你可能会释​​放你仍然分配给该属性的对象。

我强烈建议你阅读memory management rules。它们并不冗长或难度很大,一旦你阅读并理解它们,你就再也不会想到这样的事情了。