修复内存泄漏iphone的麻烦

Posted

技术标签:

【中文标题】修复内存泄漏iphone的麻烦【英文标题】:trouble fixing memory leak iphone 【发布时间】:2011-07-27 15:46:49 【问题描述】:

我的应用程序中有 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 个字母,应用程序就会崩溃。我该如何解决这个问题?

谢谢。

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

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;,所以我不明白为什么会有内存泄漏。大家能给我一些建议吗?

再次感谢。

【问题讨论】:

课程 = 无; 【课程发布】;是泄漏。通过将其设置为 nil,您将丢失对象而无需释放它。只需使用 [course release] 即可发布。 【参考方案1】:

您在每个循环中都在泄漏。你只发布了 3 last NSString。每次你为你的 3 个变量(nameConverted、locationConverted、dateConverted)重新分配一个新的 NSString 时,你也会失去对它们指向的 NSString 对象的引用。这意味着内存泄漏。当您退出 While 循环时,您只会释放其中的最后 3 个。

【讨论】:

@Deepak :让他找到解决方案,plizz ;-) 我已经尝试按照你说的做,但我没有成功,你能看看编辑吗?谢谢。 Plizzzzz,反转两行: course = nil; 【课程发布】; !!要求 nil 指针释放某些东西是没有意义的 :-) 要求他释放指向的东西,然后为了安全起见将其设置为 nil。【参考方案2】:

您在每个 while 循环中创建一个内存块,然后只释放一次。因此,如果您的 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];

          

    

【讨论】:

正如我之前所说,如果我将 3 个版本放在 while 循环中,应用程序就会崩溃。这就是我被卡住的原因。【参考方案3】:

你试过用吗:

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

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

【讨论】:

尝试使用 NSString* nameConverted = ...。这些变量只是循环的临时变量,对吗?只需在同一行自动释放它们 在这样的循环中使用自动释放是不好的做法,因为内存会累积直到池刷新。最好在每次迭代期间手动释放。【参考方案4】:

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

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];

【讨论】:

以上是关于修复内存泄漏iphone的麻烦的主要内容,如果未能解决你的问题,请参考以下文章

iPhone内存泄漏问题?

如何排查并修复内存泄漏

iphone内存泄漏教程

iPhone 内存泄漏与商店套件

如何修复libudev内存泄漏?

getpwnam 中的内存泄漏是不是有修复或解决方法?