c - 第二次使用 sqlite3_prepare_v2 时 SQLite 崩溃

标签 c sqlite prepared-statement exc-bad-access

我在使用 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/

相关文章:

java - 删除 MySQL 表 JDBC 中的特定项目

php - mysqli_fetch_assoc()需要参数/调用成员函数bind_param()错误。如何获取并修复实际的mysql错误?

c - 为什么我不能输入两个带空格的字符串?

.net - 从 .NET 与 SQLite 对话的最佳/最简单方法是什么?

c - 如何从类型 `void*` 发送指向数组中元素的指针?

android - 在sqlite数据库中排序日期?

sql - 添加唯一索引。 SQLite3

postgresql - PostgresQL 中的参数嗅探/绑定(bind)查看

Linux 程序之间的通信

c - 帮助理解宏观