2016-04-28 6 views
0

sqlite3との接続が完了しない状況があります。これは私のチームメイトのコードでしたが、彼はチームを去りましたが、現在はコードの問題を解決しようとしていますが、かなり失われています。プログラムがコンパイルされ、QtCreatorのデバッガツールで問題箇所を見つけることができました。デバッガツールは問題のためにsqlite_prepare_v2に私を連れて行きます。sqlite3、C++接続、クエリを実行する、sqlite3_prepare_v2()

デバッガ出力は次のとおりです。(私はこれを掲示しています、それが有用である可能性があるため)

 nByte 84 size_t 
     query "SELECT username,password FROM users WHERE username='dilsizk' AND password='12345678'" std::string 
     return_matrix <not accessible> std::vector<std::vector<std::string>> 
     return_value 32745 int 
     this @0x7fe90ab23f5f DBHandler 
      columns_ -1282717696 int 
      db_connection_ 0x740000800003f7da sqlite3 * * 
      log @0x7fe90ab23f5f Log 
       count -1064971727 int 
      query_ 0x401f0fc35bd08908 sqlite3_stmt * * 
      return_matrix_ 0xc748eb7501046e83 std::vector<std::vector<std::string>> * 
     unusedSQL "12345678" char * 

メソッドのコードは次のとおりです。

//query must be nul-terminated (ending in \0) 
//if an error code is returned, method returns what it has processed to that point 
std::vector<std::vector<std::string>>* DBHandler::runQuery(std::string query) { 
    //get byte size of query 
    size_t nByte = std::strlen(query.c_str()); 
    //log 
    log << "DBHandler: Query size is " + std::to_string((int)nByte) +" bytes"; 
    //make junk variable for potential unused sql 
    const char **unusedSQL; 
    //prepare the statement 
    sqlite3_prepare_v2(*db_connection_,query.c_str(),(int)nByte,query_,unusedSQL); 
    //log 
    log << "DBHandler: Query formatted into prepared statement"; 
    //perform first step, grab return value 
    int return_value = sqlite3_step(*query_); 
    //log 
    log << "DBHandler: First evaluation step completed"; 
    //check if done, and if it is because of an error or that there is only 1 row 
    if(return_value != SQLITE_ROW) { 
     //log 
     log << "DBHandler: Query returns only 1 row"; 
     if(return_value != SQLITE_DONE) { 
      //log 
      log << "DBHandler: Error handling query, code 1"; 
      return (new std::vector<std::vector<std::string>>); 
     } 
    } 

方法によりますが、私はそこにありますプログラムが次のステップに進むことができないので、すべてを投稿したくはありませんでした。

sqlite3_prepare_v2(*db_connection_,query.c_str(),(int)nByte,query_,unusedSQL); 

さらに、 ide変数のdbhandler.hのヘッダ。

#include <algorithm> 
#include <sqlite3.h> 
#include <vector> 
#include <cstring> 
#include "log.h" 

#include <iostream> 

/* Class to handle interaction with the local test database in the /db_tools directory. Run ./newDB.sh in that directory prior to use. */ 
class DBHandler { 

public: 
    /* Constructor to create DBHandler object. */ 
    /*! 
    * This object should ALWAYS be destroyed by its destructor when use is done. The constructor only opens a connection to the local database. 
    */ 
    DBHandler(); 
    /* Destructor to prevent memory leaks from this object. */ 
    /*! 
    * Important that this is called, as it is otherwise vulnerable to causing multiple memory leaks. 
    */ 
    ~DBHandler(); 
    /* Runs a query to the database and returns the output in a formatted vector. */ 
    /*! 
    * This method formats the query, passed as a string, into a prepared statement to be processed. 
    * \param query The query to the database. Must be nul-terminated (ending in \0) with no whitespace between the end of the query and the zero-terminator. 
    * \return Returns a vector, where each index holds a vector per column, whose 0 index is the column name and all following indices are entries in order of their row. 
    */ 
    std::vector<std::vector<std::string>>* runQuery(std::string query); 

private: 
    Log log; 
    sqlite3** db_connection_; /** Database connection object. **/ 
    sqlite3_stmt** query_; /** Prepared statement object. **/ 
    int columns_; /** Number of columns in the prepared statement after 1 step. **/ 
    std::vector<std::vector<std::string>>* return_matrix_; /** Pointer to the matrix containing the evaluation of the prepared statement. **/ 
    /* Fills the return matrix with the names of the columns in the prepared statement. */ 
    void fillColName(); 
    /* Fills each column vector in the return matrix with the entries from the most recent step of the prepared statement. */ 
    void fillRow(); 
}; 

私は多くのテキストのために申し訳ありませんが、私はこれらの出力は、問題を解決しようとしているときに便利だろうと思いました。

私が提供できる他のものがある場合、または質問に何か不足がある場合は教えてください。私のウェブサイトはかなり新しいです。書式設定された質問をすることができます。

ありがとうございました。

答えて

0

によると、sqlite_prepare_v2の最後のパラメータは、残りのSQL文を受け取るポインタの場所です(prepareはクエリの最初のsql文をコンパイルするだけなので)。

コードでは、初期化されていない変数がそのパラメータとして渡されているため、sqlite_prepare_v2がポインタの値を変更しようとすると、ランダムなメモリが上書きされます。

使用代わりに、このような何か:またsqlite3_prepare_v2に第四パラメータがコンパイル文を受け取る変数へのポインタであると考えられる

const char *unusedSQL = NULL; 
//prepare the statement 
sqlite3_prepare_v2(*db_connection_,query.c_str(),(int)nByte,query_,&unusedSQL); 

、あなたのコードは、のメンバ変数である_queryを渡していますあなたのクラスは、どのように初期化されているかを示していません。私はこれがunusedSQLと同じ問題だと思う。

あなたは

sqlite3_stmt* query_ 

に宣言を変更し、query_パラメータへのポインタを通過する必要があります。

const char *unusedSQL = NULL; 
query_ = NULL; 
//prepare the statement 
sqlite3_prepare_v2(*db_connection_,query.c_str(),(int)nByte, &query_, &unusedSQL); 

も注意してください。sqlite3_prepare_v2は、戻り値を持っている - あなたはどうかを確認するために、それをチェックする必要がありますすべてがうまくいった。

+0

はい、あなたの提案に応じて変更しました!私はそれを理解することができましたが、あなたは私ができるよりはるかに優れた説明をしました。ありがとうございました。 –

関連する問題