iOS中的Sqlite内存问题
我花了几个小时试图解决这个问题,但我已经放弃了;我不知道怎么了 在我的应用程序中,我执行嵌套SQL操作以正确设置所有对象。出于某种原因,有时候sqlite3对象没有得到正确的释放,导致内存急剧增加。我理解正确使用sql3_close和sql3_finalize是一个问题。然而,正如你将看到的,我认为我正确地使用了它们 以下是问题的根源:iOS中的Sqlite内存问题,ios,memory,memory-management,sqlite,Ios,Memory,Memory Management,Sqlite,我花了几个小时试图解决这个问题,但我已经放弃了;我不知道怎么了 在我的应用程序中,我执行嵌套SQL操作以正确设置所有对象。出于某种原因,有时候sqlite3对象没有得到正确的释放,导致内存急剧增加。我理解正确使用sql3_close和sql3_finalize是一个问题。然而,正如你将看到的,我认为我正确地使用了它们 以下是问题的根源: - (NSArray *) getAllSessions { if (sqlite3_open(dbPath, &db) == SQLITE_O
- (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);
}
}
因此,这里是一个混乱的记忆:
- (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对象不能正确释放
我希望你能理解我的问题,这让我快发疯了 在这样的单用户应用程序中,无需不断地打开和关闭。这与基于服务器的应用程序不同,在基于服务器的应用程序中,您与多个用户建立连接池,而保持连接会破坏连接池并损害可伸缩性。在手机应用程序中,打开并保持打开状态。完成后关闭它。至少,在递归调用中这样做 更糟糕的是,您在递归调用中打开和关闭—只需让它保持打开状态 此外:
- 您没有检查finalize的返回代码
- 您没有检查close的返回代码
- 您正在准备(编译)语句,但没有将它们保存在已保存语句上的off-call reset并再次执行
- (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;
}
}
我遇到了同样的问题。
当我使用并打开FMDB时,它工作正常。但在其他回调中,它失败并引发了“关闭泄漏语句”异常。最后我发现这是因为我保留了[FMDatabase databaseWithPath:dbPath]中的指针,而指针是一个自动释放对象。我通过以下方式解决了问题:
FMDatabase *db = [[FMDatabase databaseWithPath:dbPath] retain];
当您要关闭数据库时:
db[关闭];
[数据库释放];
db=零
这样,您就不必总是为每个操作打开和关闭数据库,数据库应该是一个管理器对象。当管理器启动时,数据库始终处于打开状态,直到管理器停止。数据库已经在getAllSessions中打开,重新打开然后关闭会把它搞砸。然后在这两种方法中都声明了一个返回类型,但没有返回任何内容。xcode没有对此抱怨吗?我没有包含所有代码来保持简单。关于你的第一点,我同意,但是为什么第一次有效而第二次无效呢?一直以来都是令人敬畏的开局和收局,非常感谢!