【问题标题】:Function that uses SQLite3 using a lot of RAM, do I have a memory leak?使用大量 RAM 的 SQLite3 函数,我有内存泄漏吗?
【发布时间】:2014-03-13 14:18:19
【问题描述】:

我有一个带有 select 语句的函数,它从一个表中获取一些信息,并使用该信息的一部分来使用另一个 select 语句从另一个表中获取更多信息。然后该函数将两个表中的信息添加到对象数组中。

看起来很简单,但是每次加载使用该函数的 ViewController 时,内存使用量都会上升,并且再也不会下降。如果我注释掉对这个函数的调用,那么内存使用情况就很好了。

-(void)displayExhibitor
{

    arrayOfExhibitors = [[NSMutableArray alloc] init];

    if (sqlite3_open([[self filePath] UTF8String], &congressDB) == SQLITE_OK){

        sqlite3_stmt *sqlStatementExhibitor;
        NSString *sqlQuery = [NSString stringWithFormat:@"SELECT * FROM Exhibitor ORDER BY Name"];
        const char *sqlQueryChars = [sqlQuery UTF8String];

        if (sqlite3_prepare(congressDB, sqlQueryChars, -1, &sqlStatementExhibitor, NULL)==SQLITE_OK) {

            while (sqlite3_step(sqlStatementExhibitor)==SQLITE_ROW) {

                NSString *name = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(sqlStatementExhibitor, 1)];
                NSString *category = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(sqlStatementExhibitor, 4)];
                NSString *description = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(sqlStatementExhibitor, 5)];
                NSString *locationID = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(sqlStatementExhibitor, 3)];
                NSString *location;
                // Get exhibitor location information from location table
                sqlite3_stmt *sqlStatementLocation;
                NSString *sqlQueryLocation = [NSString stringWithFormat:@"SELECT Name FROM Location WHERE _ID = '%@'", locationID];
                const char *sqlQueryCharsLocation = [sqlQueryLocation UTF8String];

                 if (sqlite3_prepare(congressDB, sqlQueryCharsLocation, -1, &sqlStatementLocation, NULL)==SQLITE_OK) {

                     while (sqlite3_step(sqlStatementLocation)==SQLITE_ROW) {

                         location = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(sqlStatementLocation, 0)];

                     }

                 } else {

                     NSLog(@"There was a problem with get location - %s",sqlite3_errmsg(congressDB));

                 }
                 sqlite3_finalize(sqlStatementLocation);

                Exhibitor *exhibitor = [[Exhibitor alloc] init];
                [exhibitor setName:name];
                [exhibitor setCategory:category];
                [exhibitor setDescription:description];
                [exhibitor setLocation:location];

                [arrayOfExhibitors addObject:exhibitor];

            }

        } else {

            NSLog(@"There was a problem with prepare- %s",sqlite3_errmsg(congressDB));

        }
        sqlite3_finalize(sqlStatementExhibitor);

    } else {

        NSLog(@"There was a problem with DB open - %s",sqlite3_errmsg(congressDB));

    }

    [[self tableView]reloadData];

}

是因为我在另一个里面有一个 SQLite3_prepare 吗?

编辑: 我刚刚尝试将代码精简到最低限度:

-(void)testFunction
{
    sqlite3_stmt *sqlStatementExhibitor;
    NSString *sqlQuery = [NSString stringWithFormat:@"SELECT * FROM Exhibitor ORDER BY Name"];
    const char *sqlQueryChars = [sqlQuery UTF8String];
    if (sqlite3_open([[self filePath] UTF8String], &congressDB) == SQLITE_OK){
        if (sqlite3_prepare(congressDB, sqlQueryChars, -1, &sqlStatementExhibitor, NULL)==SQLITE_OK) {
            while (sqlite3_step(sqlStatementExhibitor)==SQLITE_ROW) {  
                NSLog(@"Row found");
            }
        } else {
            NSLog(@"There was a problem with prepare- %s",sqlite3_errmsg(congressDB)); 
        }
        sqlite3_finalize(sqlStatementExhibitor);
    }
}

每次运行时仍然会增加大约 250KB 的内存使用量,这是怎么回事?有没有办法可以手动从内存中释放 SQL 连接?

【问题讨论】:

  • 这就是全部功能吗?
  • 是的,就是这样。整个 ViewController.m 文件有更多代码,但这似乎是罪魁祸首,即如果我将其注释掉,内存问题就会消失。

标签: ios cocoa-touch memory-leaks sqlite


【解决方案1】:

您忘记close 数据库连接。 这将泄漏数据库对象本身和所有页面缓存。

【讨论】:

  • 我假设(并阅读)在 iOS 应用程序中使用 SQLite3 的“正确”方法是在应用程序启动时打开数据库一次,然后关闭它一次,就像应用程序一样即将关闭。不是这样吗?在我需要之前打开数据库并在之后关闭它会更好吗?
  • 但是你没有打开一次;您在每个函数调用中打开一个新连接。
  • 我完全错过了这样一个事实,即我确实每次都在打开一个新连接 - if (sqlite3_open([[self filePath] UTF8String], &congressDB) == SQLITE_OK){ - 这不仅仅是检查一个连接,它正在打开一个。感谢您指出这一点。
猜你喜欢
  • 2011-10-20
  • 1970-01-01
  • 2013-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-02
  • 2013-09-02
  • 2015-03-07
相关资源
最近更新 更多