麻烦修复内存泄漏iphone

时间:2011-07-27 15:46:50

标签: iphone objective-c cocoa-touch

我的应用程序中有3个内存泄漏,我找不到如何修复它。我是xcode和Objective c的新手。这是我的代码:

if(sqlite3_prepare_v2( [[DatabaseController sharedDatabaseController] getDb], sqlQueryConverted, -1, &dbStatement, NULL)==SQLITE_OK){

        //Run the query
        while ( sqlite3_step(dbStatement) == SQLITE_ROW ) 
        {    


            const char *name = (const char *)sqlite3_column_text(dbStatement, 0);
            int courseId = sqlite3_column_int(dbStatement, 1);
            const char *location = (const char *)sqlite3_column_text(dbStatement, 2);
            const char *date = (const char *)sqlite3_column_text(dbStatement, 3);

            //Convert the returnedElement char to string
            nameConverted = [[NSString alloc] initWithUTF8String:name];
            locationConverted = [[NSString alloc] initWithUTF8String:location];
            dateConverted = [[NSString alloc] initWithUTF8String:date];

            Course *course = [[[Course alloc]initWithName:nameConverted _id:courseId location:locationConverted courseDate:dateConverted] autorelease];

            //Add the course to the to a temporary list to remove duplicated items            
            [tempResults addObject:course];

        }  
        [nameConverted release];
        [locationConverted release];
        [dateConverted release];
    }

我也尝试过自动退款。此代码用于过滤搜索并重新加载搜索显示表。如果我将release行放在while语句中,如果我键入2个字母,应用程序将崩溃。我怎么能解决这个问题?

感谢。

编辑:我一直在这个问题上来回走动,没有运气。我得出的结论是,仪器出了问题,因为它仍然显示内存泄漏。这是今天的代码,我认为应该解决问题:

NSString *nameConverted = [[NSString alloc] initWithUTF8String:name];
            NSString *locationConverted = [[NSString alloc] initWithUTF8String:location];
            NSString *dateConverted = [[NSString alloc] initWithUTF8String:date];

            Course *course = [[[Course alloc]initWithName:nameConverted _id:courseId location:locationConverted courseDate:dateConverted] autorelease];

            //Add the course to the to a temporary list to remove duplicated items            
            [tempResults addObject:course];
            course = nil;
            [course release];
            [nameConverted release];
            nameConverted = nil;
            [locationConverted release];
            locationConverted = nil;
            [dateConverted release];
            dateConverted = nil;
            NSLog(@"course retain count %i",[course retainCount]);
            NSLog(@"name coverted retain count %i",[nameConverted retainCount]);
            NSLog(@"location coverted retain count %i",[locationConverted retainCount]);
            NSLog(@"date coverted retain count %i",[dateConverted retainCount]);

日志告诉我retainCount = 0;所以我不明白为什么会有内存泄漏。你能给我一些建议吗?

再次感谢。

4 个答案:

答案 0 :(得分:2)

你在每个循环都漏掉了。你只发布了3个持续的NSString。每当你为你的3个变量(nameConverted,locationConverted,dateConverted)重新分配一个新的NSString时,你就会失去对它们所指向的NSString对象的引用。这意味着内存泄漏。当你离开While循环时,你只释放最后的3个。

答案 1 :(得分:1)

您在每次循环时创建一个内存块,然后只释放一次。因此,如果while循环运行超过10次,则每个字符串的保留计数为10,但只释放一次。

要修复,请将3个版本放入while循环中,如下所示:

if(sqlite3_prepare_v2( [[DatabaseController sharedDatabaseController] getDb], sqlQueryConverted, -1, &dbStatement, NULL)==SQLITE_OK){

        //Run the query
        while ( sqlite3_step(dbStatement) == SQLITE_ROW ) 
        {    


            const char *name = (const char *)sqlite3_column_text(dbStatement, 0);
            int courseId = sqlite3_column_int(dbStatement, 1);
            const char *location = (const char *)sqlite3_column_text(dbStatement, 2);
            const char *date = (const char *)sqlite3_column_text(dbStatement, 3);

            //Convert the returnedElement char to string
            nameConverted = [[NSString alloc] initWithUTF8String:name];
            locationConverted = [[NSString alloc] initWithUTF8String:location];
            dateConverted = [[NSString alloc] initWithUTF8String:date];

            Course *course = [[[Course alloc]initWithName:nameConverted _id:courseId location:locationConverted courseDate:dateConverted] autorelease];

            //Add the course to the to a temporary list to remove duplicated items            
            [tempResults addObject:course];

        [nameConverted release];
        [locationConverted release];
        [dateConverted release];

        }  

    }

答案 2 :(得分:0)

您是否尝试过使用:

nameConverted = [[NSString initWithUTF8String:name] autorelease];
locationConverted = [[NSString initWithUTF8String:location] autorelease];
dateConverted = [[NSString initWithUTF8String:date] autorelease];

并删除循环外的版本? 也不要自动移动课程对象,在将其添加到tempResults后将其释放。

答案 3 :(得分:0)

这就是你应该这样做的方式。

NSString *nameConverted = [[NSString alloc] initWithUTF8String:name];
NSString *locationConverted = [[NSString alloc] initWithUTF8String:location];
NSString *dateConverted = [[NSString alloc] initWithUTF8String:date];

Course *course = [[Course alloc] initWithName:nameConverted _id:courseId location:locationConverted courseDate:dateConverted];
[tempResults addObject:course];
[course release];

[dateConverted release];
[locationConverted release];
[nameConverted release];