iOS中的Sqlite内存问题 [英] Sqlite in iOS memory issues

查看:71
本文介绍了iOS中的Sqlite内存问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我花了数小时试图解决这个问题,但我刚刚放弃了.我不知道怎么了.

I spent hours trying to fix that but I've just given up; I have no idea what's wrong.

在我的应用程序中,我执行嵌套SQL操作以正确设置所有对象.由于某些原因,有时sqlite3对象无法正确释放,从而导致内存上升.我了解正确使用sql3_close和sql3_finalize是一个问题.但是,如您所见,我认为我已经正确使用了它们.

In my app, I do nested SQL operations to set all my objects correctly. For some reason, sometimes the sqlite3 objects do not get release properly, causing the memory to go up the roof. I understand it is a problem with using correctly sql3_close and sql3_finalize. However, as you will see, I think I have used them correctly.

这是问题的根源:

- (NSArray *) getAllSessions {
    if (sqlite3_open(dbPath, &db) == SQLITE_OK) { 
        if (sqlite3_prepare_v2(db, query_stmt, -1, &statement, NULL) == SQLITE_OK) {
            while (sqlite3_step(statement) == SQLITE_ROW) {

                //I found out that doing something like that
                //toAdd.in_loc = [self getIndoorLocationWithId:[NSNumber numberWithInt:(int)sqlite3_column_int(statement, 6)]];
                //messes the memory up all the time
                //but doing that works OK:
                NSNumber *_id = [[NSNumber alloc]  initWithInt:(int) sqlite3_column_int(statement, 5)];
                toAdd.out_loc = [self getOutdoorLocationWithId:_id];
                [_id release];

                //So I did the same with the second one, but this one messes memory up:
                NSNumber *id2 = [[NSNumber alloc] initWithInt:(int)sqlite3_column_int(statement, 6)];
                toAdd.in_loc = [self getIndoorLocationWithId:id2];
                [id2 release];
            }
            sqlite3_finalize(statement);
        }
        sqlite3_close(db);
    } 
}

这是使内存混乱的一个原因:

So here is the one that messes memory up:

- (IndoorLocation *) getIndoorLocationWithId:(NSNumber *) locId {
    if (sqlite3_open([databasePath UTF8String], &db) == SQLITE_OK) { 
        if (sqlite3_prepare_v2(db, query_stmt, -1, &statement, NULL) == SQLITE_OK) {
            while (sqlite3_step(statement) == SQLITE_ROW) {  
                //if I comment the thing below it works
                NSNumber *_id = [[NSNumber alloc]  initWithInt:(int) sqlite3_column_int(statement, 5)];
                toReturn.outLoc = [self getOutdoorLocationWithId:_id];
                [_id release];

            }
            sqlite3_finalize(statement);
        }
        sqlite3_close(db);
    }
}

因此,在使内存混乱的情况下,我以与第一次使用完全相同的功能(getOutdoorLocationwithId),以相同的方式使用,但它不起作用,不会正确释放sqlite3对象.

So in the one that messes memory up, I use exactly the same function as the first time (getOutdoorLocationwithId), in the same way but it doesn't work, sqlite3 objects don't get released properly.

希望您能理解我的问题,这让我发疯了!

I hope you understand my problem, this is driving me nuts!

推荐答案

在这样的单个用户应用程序中,无需持续打开和关闭.这与基于服务器的应用程序不同,在该应用程序中您与多个用户建立了连接池,而保持连接可能会破坏该池并损害可伸缩性.在电话应用程序中将其打开并保持打开状态.完成后将其关闭.至少要在递归调用中执行此操作.

In a single user app like this, there's no need to continually open and close. This is not like a server based app where you have connection pooling with multiple users where holding the connection can defeat the pool and hurt scalability. In a phone app open it and hold it open. close it when you're done. At a minimum, do that within a recursive call.

更糟糕的是,您正在递归调用中打开和关闭-只需保持打开状态即可.

To make it worse, you're opening and closing within recursive calls - just leave it open.

也:

  • 您没有检查finalize的返回码
  • 您没有检查close的返回码.
  • 您正在准备(编译)语句,但没有将其保存下来-对已保存的语句调用reset并再次执行.

考虑使用FMDB-这是一个很好的包装器.

Consider using FMDB - it's a good wrapper.

顺便说一句,这是一个更丰富,更持久的关闭,但请不要在每次通话时都使用它.在结束或应用程序进入后台时将其关闭...这是我的,与fmdb相似.

BTW, here's a richer and more durable close but don't use it on every call. Close it when you're ending or your app is going into the background ... This is mine which is similar to what fmdb does.

- (void)close
{
    if (_sqlite3)
    {
        ENInfo(@"closing");
        [self clearStatementCache];

        int rc = sqlite3_close(_sqlite3);
        ENDebug(@"close rc=%d", rc);

        if (rc == SQLITE_BUSY) 
        { 
            ENError(@"SQLITE_BUSY: not all statements cleanly finalized");

            sqlite3_stmt *stmt; 
            while ((stmt = sqlite3_next_stmt(_sqlite3, 0x00)) != 0) 
            {
                ENDebug(@"finalizing stmt");
                sqlite3_finalize(stmt); 
            }

            rc = sqlite3_close(_sqlite3);
        }

        if (rc != SQLITE_OK)
        {
            ENError(@"close not OK.  rc=%d", rc);
        }

        _sqlite3 = NULL;
    }
}

这篇关于iOS中的Sqlite内存问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆