【问题标题】:Memory leaks in iphone applicationiPhone应用程序中的内存泄漏
【发布时间】:2011-07-29 11:43:52
【问题描述】:

大家好!我是iphone开发的新手。我有内存泄漏的问题。我有这样的代码。

do {

    int s = sqlite3_step(statement);
    switch (s) {
        case SQLITE_ROW:{

            Article *a = [[[Article alloc] init] autorelease];
            for (int i = 0; i < columnCount; i++) {
                const char *columnName = sqlite3_column_name(statement, i);
                if(strncmp(columnName, "title", strlen("title")) == 0){
                    const char* colStr = (char*)sqlite3_column_text(statement, i);
                    if(colStr != NULL)
                        a.title = [[[NSString alloc] initWithCString: colStr encoding:NSUTF8StringEncoding] autorelease];
                    continue;
                }
                if(strncmp(columnName, "author", strlen("author")) == 0){
                    const char* colStr = (char*)sqlite3_column_text(statement, i);
                    if(colStr != NULL)
                        a.author = [[[NSString alloc] initWithCString:colStr encoding:NSUTF8StringEncoding] autorelease];
                    continue;
                }
                if(strncmp(columnName, "description", strlen("description")) == 0){
                    const char* colStr = (char*)sqlite3_column_text(statement, i);
                    if(colStr != NULL)
                        a.description = [[[NSString alloc] initWithCString:colStr encoding:NSUTF8StringEncoding] autorelease];
                    continue;
                }
                if(strncmp(columnName, "link", strlen("link")) == 0){
                    const char* colStr = (char*)sqlite3_column_text(statement, i);
                    if (colStr) 
                        a.link = [[[NSString alloc] initWithCString:colStr encoding:NSUTF8StringEncoding] autorelease];
                    continue;
                }
                if(strncmp(columnName, "imageUrl", strlen("imageUrl")) == 0){
                    const char* colStr = (char*)sqlite3_column_text(statement, i);
                    if (colStr)
                        a.imageUrl = [[[NSString alloc] initWithCString:colStr encoding:NSUTF8StringEncoding] autorelease];
                    continue;
                }
                if(strncmp(columnName, "pubDate", strlen("pubDate")) == 0){
                    const char* colStr = (char*)sqlite3_column_text(statement, i);
                    if(colStr)
                        a.pubDate = [[[NSString alloc] initWithCString:colStr encoding:NSUTF8StringEncoding] autorelease];
                    continue;
                }
            }
            [array insertObject:a atIndex:0];
        }
        break;
        case SQLITE_DONE:
            sqlite3_finalize(statement);
            dataForReadingAvailable = NO;
            break;
        default:{
            NSLog(@"getArticlesForFeed:sqlite3_step failed.Error:%s",sqlErrMsg);
            return nil;
        }
        break;
    }   
}while(dataForReadingAvailable);

Xcode 的工具显示,当我分配对象和初始化它的属性时,我有内存泄漏。但是为什么会这样。所有对象都是自动释放的,所以我认为不会是这种情况。 谢谢。

【问题讨论】:

  • 你在做什么sqlite3_close(database);
  • 没有。我在开始时打开数据库并在完成时关闭
  • 它是否说 which 对象正在泄漏? (专业提示:重构代码可能有助于轻松发现问题)

标签: iphone objective-c memory-leaks


【解决方案1】:

我想也许你在某处用新指针覆盖了分配的内存。

我会替换

Article *a = [[[Article alloc] init] autorelease];

Article *a = [[Article alloc] init];
//some code
[a release]; //when you don't need it anymore

这不是一个使用自动释放的好习惯。如果有很多对象,它甚至可以减慢您的应用程序的速度。 还有像

这样的字符串
 a.title = [[[NSString alloc] initWithCString: colStr encoding:NSUTF8StringEncoding] autorelease];

我会替换为

 a.title = [NSString stringWithCString:colStr encoding:NSUTF8StringEncoding];

在这种情况下,您还依赖自动释放池,但它要简单得多。

编辑: 实际上,您的“文章”分配是在 do-while 循环中。 在字符串 [array insertObject:a atIndex:0]; 中,您的 aray 保留了对象,您不再需要它,但您依赖自动释放。分析器(或您正在使用的工具)看到,您将分配放置在循环的主体中,而没有在每次迭代后释放它。这样,在循环的第二次迭代中,您将覆盖您的“a”对象,从而丢失旧指针并以这种方式泄漏内存(池不会找到此指针,因为“a”已被覆盖)。即使您只通过循环一次,分析器也不会在意并给您一个警告。

【讨论】:

  • 感谢您的提示,但我不能依赖垃圾收集器,因为 iO 中缺少它。
  • 当然 :),你说得对,我的意思是自动释放池。此代码适用于 iOS。
  • 最好尽可能使用自动释放。 (google-styleguide.googlecode.com/svn/trunk/…)。但是,在这种情况下,如果您创建了很多字符串,则应该分配/初始化/释放,因为在您离开函数之前可能不会发生自动释放,而且可能为时已晚。
  • "iPhone OS 注意:因为在 iPhone OS 上,应用程序在更受内存限制的环境中执行,所以不鼓励在应用程序的方法或代码块(例如循环)中使用自动释放池创建许多对象。相反,您应该尽可能显式释放对象。 (c) (苹果文档)
猜你喜欢
  • 1970-01-01
  • 2011-01-05
  • 1970-01-01
  • 2014-02-06
  • 2011-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多