【问题标题】:Leaks while adding to array in while loop在 while 循环中添加到数组时泄漏
【发布时间】:2011-08-13 20:11:32
【问题描述】:

我有一个函数名为:- (void) AddSortedCustomFeed :(NSMutableArray*) rssList; 这个函数将项目(文章)从 sqlite 数据库添加到 NSMutableArray 这里这个函数是如何工作的:

- (void) AddSortedCustomFeed :(NSMutableArray*)rssList {    
    NSLog(@"\n\n\n ----- Add Sorted SQL Database -----");
    NSLog(@"Start");
    // Create Query String.
    NSString* sqliteQuery = [NSString stringWithFormat:@"SELECT mainLink, title, summary, pubDate, author, imageLink, body, favorites, pubdatetime FROM ARTICLES WHERE customfeed  = 'Y' ORDER BY pubdatetime DESC"];
    NSLog(@"Query String is: %@", sqliteQuery);
    // Pointer to Article and Statement.
    Article* article;
    sqlite3_stmt* statement;

    // Prepare SQL for work.
    if( sqlite3_prepare_v2(articlesDB, [sqliteQuery UTF8String], -1, &statement, NULL) == SQLITE_OK ) {
        // Get next row from database.
        while( sqlite3_step(statement) == SQLITE_ROW ) {
            // Alloc and init article.

            article = [[Article alloc] initWithValues:[NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 1)] 
                                             mainLink:[NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 0)] 
                                              summary:[NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 2)] 
                                              pubDate:[NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 3)] 
                                               author:[NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 4)] 
                                            imageLink:[NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 5)] ];


            //article.body      = [NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 6)];
            NSString* favo    = [NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 7)];
            article.favorite  = [favo hasPrefix:@"N"] ? NO : YES; 

            // Add to list.
            [rssList addObject:article];
            // Release article.
            [article release];
        }
    }
    else NSLog( @"SortSQLDatabase: Failed from sqlite3_prepare_v2. Error is:  %s", sqlite3_errmsg(articlesDB) );

    // Finalize and close database.
    sqlite3_finalize(statement);

    NSLog(@"End\n\n\n");
}

如何在这个函数中看到我创建文章Article* article; 并在while 循环中分配并初始化它。之后,我将 Article 对象添加到 NSMutableArray 然后释放它,但随后我调用 [article release]; 女巫必须调用它不调用的 delloc 函数?我不明白为什么。我尝试了不同的方法,但我所有的尝试都崩溃了。这是关于文章类的文章 - link

【问题讨论】:

  • @kubi - 感谢您的编辑。我确实知道女巫也会捕猎韭菜,但这与编程没有太大关系。 :-)

标签: iphone loops memory-leaks while-loop iso


【解决方案1】:

没有在 Article 对象上调用dealloc,因为[rssList addObject:article] 保留 article 对象。所以你的保留计数是 1,它不会被释放。现在如果你释放 rssList(或从数组中删除文章对象),保留计数将达到 0,并且该对象将被释放。

P.S:如果您有这样的 while 循环,我建议您添加一个自动释放池以避免自动释放对象堆积。

while( .. )
{
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  // .. your code .. //
  [pool release];
}

P.P.S:如果您点击“Shift+Cmd+A”,XCode 将 statically analyze 您的代码并查找泄漏/内存事故。我感觉它会找到一些。

【讨论】:

    【解决方案2】:

    你有几个选择,你应该尝试看看你想做什么。基本上,一旦您发送了[article release];,您将需要从头开始制作article。所以你可以做类似的事情

    Article *article = [[Article alloc] initWithValues:[NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 1)] 
                                             mainLink:[NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 0)] 
                                              summary:[NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 2)] 
                                              pubDate:[NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 3)] 
                                               author:[NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 4)] 
                                            imageLink:[NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 5)] ];
    

    然后将[article release]; 留在现在的位置。不过,请务必从上面取出您的Article* article; 行。这可能是您不想要的大量开销。

    您可以保持所有内容不变并将[article release]; 向下移动,这样它就在循环之外。

    【讨论】:

    • 您总是可以在 alloc 语句末尾的循环内添加autorelease。这不是最干净的解决方案。您还应该查看 MiRAGEe 的答案。我只是想帮你避免崩溃。
    猜你喜欢
    • 2011-03-13
    • 1970-01-01
    • 1970-01-01
    • 2012-04-15
    • 1970-01-01
    • 2022-08-09
    • 2020-08-24
    • 1970-01-01
    • 2022-01-21
    相关资源
    最近更新 更多