2015-01-22 1 views
0

Я использую SQLite 3 в моем приложении C. До сих пор он работал как шарм, когда я начал писать модульные тесты. Функция, о которой идет речь, довольно маленькая. Он открывает базу данных в памяти, готовит заявление, а затем делает некоторые вещи с ним. Проблема в том, что приложение вылетает с ошибкой сегментации при вызове функции sqlite3_prepare_v2. Я попытался отладить его и проверить, чтобы все аргументы были действительными, какими они кажутся.Подготовка инструкции SQLite 3 segfault

Ниже я ввел минимальный пример, который вызывает segfault таким же образом. Backtrace перечисляет sqlite3LockAndPrepare как функцию, где он сбой (вызывается sqlite3_prepare_v2).

Как уже упоминалось выше, я использую SQLite без каких-либо проблем в остальной части моего приложения. Я просто не могу понять, какая разница в использовании, так как она разделена на несколько разных подпрограмм, которые также делают другие вещи. Единственное, что я могу заметить, это использование базы данных в памяти вместо встроенного диска, но я попытался с ней на диске, и это не имело никакого значения.

#include <stdlib.h> 
#include <stdio.h> 
#include <sqlite3.h> 

int main(void) 
{ 
    sqlite3 *db; 
    sqlite3_stmt **stmt; 
    const char *str = "CREATE TABLE Test (t1 varchar(8) NOT NULL);"; 

    if (SQLITE_OK != sqlite3_open(":memory:", &db)) { 
     printf("Can't open...\n"); 
     return 1; 
    } 

    sqlite3_prepare_v2(db, str, -1, stmt, NULL); 

    return 0; 
} 
+0

никогда не использовал SQLite из c, но не является 'db' уже указателем на экземпляр sqlite, а затем вы передаете адрес указателя, а не указатель на вызов open()? –

+0

Предполагается, что это 'sqlite3 **' https://www.sqlite.org/c3ref/open.html – jacwah

+0

@fridge. Вы правы, что второй аргумент 'sqlite3_open()' должен быть 'sqlite3 ** '. И это то, что есть в образце кода. –

ответ

1

Четвертый аргумент sqlite3_prepare_v2() должен быть действительным указателем на sqlite3_stmt *. Вместо этого вы передаете неопределенное значение (поскольку ваша переменная stmt никогда не инициализируется). (Заметим также, что даже если это не крах программы, вы не можете получить указатель на подготовленное заявление таким образом.)

Вы должны сделать это, вместо того, чтобы:

int main(void) 
{ 
    sqlite3 *db; 
    sqlite3_stmt *stmt; 
    const char *str = "CREATE TABLE Test (t1 varchar(8) NOT NULL);"; 

    /* ... create database ... */  

    sqlite3_prepare_v2(db, str, -1, &stmt, NULL); 

    return 0; 
} 
Смежные вопросы