我在使用 SQLite 时遇到与内存管理相关的崩溃。除非我在 Xcode 中启用 Guard Malloc(一种测试模式),否则它只会每 30 次左右尝试崩溃一次,在这种情况下,它会在我第二次准备语句时崩溃,100% 的情况。我认为这与我打开或使用数据库的方式有关,但我找不到任何问题,但我是 SQLite 的新手。有什么我忘记的吗?
用于打开的包装函数:
int databaseConnect(sqlite3 **db){
int rc = sqlite3_open_v2(dbURL, db, SQLITE_OPEN_READWRITE, NULL);
if(rc!=SQLITE_OK){
fprintf(stderr, "Can't open database! Error: %s\n", sqlite3_errmsg(*db));
sqlite3_close_v2(*db);
return(SQL_ERROR);
}
return NO_ERROR;
}
发送命令的包装函数:
int databaseCommand(char* command, sqlite3* db){
char* error = NULL;
int ret = sqlite3_exec(db, command, NULL, 0, &error);
if (ret!=SQLITE_OK){
printf("SQL command aborted. Error: %s\n", error);
return SQL_ERROR; //EDIT: this will cause the database to close later
}
if (error) sqlite3_free(error);
return NO_ERROR;
}
我如何使用我的打开功能:
//ONCE IN MAIN THREAD, BEFORE ANY OTHER THREADS:
sqlite3* db = NULL;
databaseConnect(&db);
//call databaseCommmand a few times while creating tables...
sqlite3_close_v2(db);
//ONCE PER THREAD IN OTHER THREADS:
sqlite3* db = NULL; databaseConnect(&db);
我如何在我的非主线程中使用sqlite3_prepare_v2(以及它崩溃的地方):
struct LinkedList* databaseSelect(char* command, sqlite3* db){
sqlite3_stmt* stmt = NULL;
int retval = retval = sqlite3_prepare_v2(db,command,(strlen(command))*sizeof(char),&stmt,NULL); //crashes here the second time I run it
if(retval!=SQLITE_OK){
printf("Selecting data from database failed! Error: %s\n", sqlite3_errmsg(db));
sqlite3_free(stmt);
return NULL; //EDIT: this will cause the database to close later
}
// Then the function does stuff involving sqlite3_column_text and sqlite3_column_int…
sqlite3_free(stmt);
// return the linked list result
}
我得到的错误以及导致该错误的 SQLite3 库的部分:
EXC_BAD_ACCESS (code=1) in this part of sqlite3.c:
/*
** Create a new virtual database engine.
*/
SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3 *db){
Vdbe *p;
p = sqlite3DbMallocZero(db, sizeof(Vdbe) );
if( p==0 ) return 0;
p->db = db;
if( db->pVdbe ){
db->pVdbe->pPrev = p; //error is right here; db->pVdbe is pointing to invalid address
}
p->pNext = db->pVdbe;
p->pPrev = 0;
db->pVdbe = p;
p->magic = VDBE_MAGIC_INIT;
return p;
}
每当我使用 sqlite3_column_text 时,我都会立即复制结果。我不修改结果。在databaseCommand和databaseSelect中,char*命令以null结尾并且有效(我检查过)。每个线程都使用自己的数据库句柄,每个线程都连接到同一个数据库。然而,在此测试用例中,在任何给定时间只有一个线程连接到数据库。
如果这里确实没有任何问题,我必须假设我在程序的其他地方践踏了内存,并且在程序的其余部分中我找不到任何看起来有点危险的东西。另外,值得怀疑的是 SQLite 是每次崩溃的原因。
最佳答案
sqlite3_prepare_v2 documentation说:
The calling procedure is responsible for deleting the compiled SQL statement using sqlite3_finalize() after it has finished with it.
sqlite3_free()只能用于使用 sqlite3_alloc() 分配的原始内存,或者当诸如 sqlite3_exec() 之类的函数时使用已记录为需要它。
关于c - 第二次使用 sqlite3_prepare_v2 时 SQLite 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23508073/