2017-07-29 23 views
-2

私は以下のコードを貼り付けました。これは、sqlite3_get_table()でsegフォルトを与えます。私はテーブルの行の数を取得し、それを返すしたい。行数が0より大きい場合、プログラムはすべての行を読み取る必要があります。sqlite3プログラム受信信号SIGSEGV、sqlite3_get_table()内のセグメンテーションフォールト

int型countRowsInTable(){

   sqlite3 *db; 
       char *zErrMsg = 0; 
       int rc; 
       char const *sql; 
       char ***pazResult; 
       int *pnRow;   /* Number of result rows written here */ 
       int *pnColumn;  /* Number of result columns written here */ 

       rc = sqlite3_open("DeviceDetails.db", &db); 

       if(rc) 
       { 
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); 
        return(0); 
       } 
       else 
       { 
        fprintf(stderr, "Opened database successfully\n"); 
       } 

       /* Create SQL statement */ 
       sql = "select * from Device_Details"; 

       /* Execute SQL statement */ 
       // rc = sqlite3_exec(db, sql, 0/*callback*/, 0/*(void*)data*/, &zErrMsg); 
       rc = sqlite3_get_table(db, sql, pazResult, pnRow, pnColumn, &zErrMsg); 
       void sqlite3_free_table(char **result); 
if(rc != SQLITE_OK) 
       { 
        fprintf(stderr, "SQL error: %s\n", zErrMsg); 
        sqlite3_free(zErrMsg); 
       } 
       else 
       { 
        fprintf(stdout, "Operation done successfully\n"); 
        cout<<"rows="<<pnRow<<endl; 
        sleep(10); 
       } 
       sqlite3_close(db); 
       cout<<"num rows =" << *pnRow <<endl; 

     } 

あなたの提案を読んだ後、私は自分のコードを変更しました。ここでselect count(*)を使用しますが、(which)変数は行数を保持します。私は、sqlite3_execでコールバック関数を実装する必要があります。また、行数がゼロより大きい場合はデータを取得する必要があります。コールバック関数でデータを取得した場合、それをテーブルのcountRowsを呼び出す関数に渡す方法は?私はグローバル変数を保持することができます。コールバックが実行されるとすぐに、それは条件変数を介して呼び出し関数を通知します。だから私は新しいスレッドでcountRowsInTable関数を維持する必要があります。私はもっ​​と簡単なアプローチがありますか?

int countRowsInTable() 
     { 

       sqlite3 *db; 
       char *zErrMsg = new char[64]; 
       int rc; 
       char const *sql; 
       char ***pazResult; 
       int *pnRow = new int;   /* Number of result rows written here */ 
       int *pnColumn = new int;  /* Number of result columns written here */ 
       //*pnRow = 0; 

       **pazResult = new char[20480]; 

       rc = sqlite3_open("DeviceDetails.db", &db); 

       if(rc) 
       { 
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); 
        return(0); 
       } 
       else 
       { 
        fprintf(stderr, "Opened database successfully\n"); 
       } 

       /* Create SQL statement */ 
       sql = "select count(*) from Device_Details"; 

       /* Execute SQL statement */ 
       rc = sqlite3_exec(db, sql, 0/*callback*/, 0/*(void*)data*/, &zErrMsg); 
       //rc = sqlite3_get_table(db, sql, pazResult, pnRow, pnColumn, &zErrMsg); 
       //void sqlite3_free_table(char **result); 
       if(rc != SQLITE_OK) 
       { 
        fprintf(stderr, "SQL error: %s\n", zErrMsg); 
        sqlite3_free(zErrMsg); 
       } 
       else 
       { 
        fprintf(stdout, "Operation done successfully\n"); 


       } 


     } 
+0

char * zErrMsg = 0;を変更してみてください。 char ** zErrmsgに; – Ihdina

+0

常に警告を有効にしてコードをコンパイルしてください。 –

+0

これは役に立ちません –

答えて

1

あなたは正しいパラメータで関数を呼び出していません。初期化されていないポインタを渡していますが、変数を作成してポインタを渡す必要があります。そのため、SQLiteは値を書き込むことができます。

const char *sql = "select * from Device_Details"; 
char **result; 
int nrow; 
int ncolumn; 
char *errmsg; 
int rc; 

rc = sqlite3_get_table(db, sql, &result, &nrow, &ncolumn, &errmsg); 

ただし、SQLiteのマニュアルが機能の使用を思いとどまら知っておく必要があります。「これは後方互換性のために保存されているレガシーインタフェースでは推奨されません。このインタフェースを使用します。。」

また、おそらく誤って貼り付けたvoid sqlite3_free_table(char **result)を削除する必要があります。

+0

もしそれが非難されたら、他に何を使うべきですか? 0より大きい場合はすべてのデータを読み込む必要があります –

+0

'sqlite3_prepare'を使用してSQL文をコンパイルし、' sqlite3_step'を実行して行を取得し、 'sqlite3_finalize'を使用して終了します。このAPIについては、https://www.sqlite.org/cintro.htmlを参照してください。 –

関連する問題