sql3_finalize创建一个段错误

时间:2014-04-21 12:24:07

标签: c++ sqlite segmentation-fault

我试图使用SQLite编写一个从命令文件创建zSQL数据库的函数。我的功能代码如下:

bool createDatabaseFromFile(Database& db, std::istream &commandFile, const char* dbName, std::ostream* err, bool multilineQueries)
{
    Statement stmt;
    std::string lineStr;
    std::string queryStr;

    bool end = false;

    if (!dbName)        // if the adress of the database isn't given, we get it from the first line of the command file
    {
        std::getline(commandFile, lineStr);
        dbName = lineStr.c_str();
    }

    bool noError = db.open(dbName, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, err); // if the database didn't open, the following loops aren't used

    while (std::getline(commandFile, lineStr) && (!end) && noError) // adds all lines of the file until either the end of the file or the keyword "#END"
    {
            if (lineStr.substr(0,4) == "#END")
            end = true;

            else if (lineStr.substr(0,2) != "//")  // skips the commented lines
            queryStr += lineStr;

            if (!multilineQueries)                  // if all lines are considered as a single query
            queryStr += ";";
    }

    std::string::size_type start_query = 0;
    std::string::size_type end_query;
    std::string query;

    while (start_query != std::string::npos && !noError)    //continue until all queries of the string are executed or there is an error
    {
        end_query = queryStr.find_first_of(';', start_query);
        query = queryStr.substr(start_query, end_query);

        if (db.prepare(query.c_str(), lineStr.size(), stmt))    // returns true if sql3_prepare didn't return an error
        {
            noError = stmt.makeAllSteps();
        }

        else
        noError = false;

        start_query = end_query;

        if (start_query != std::string::npos)
        start_query ++;                             // else the "cursors" stay on the same ';' over and over
    }


    return noError;
}

Stmt类基本上是sqlite3_stmt的包装器。当它在代码末尾被销毁时,它会调用sqlite3_finalize,这会导致出现段错误,这是我无法理解的。问题是什么?

错误的调用堆栈是:

sqlite3_finalize(pStmt=0x3)
sql3::Statement::erase(this=0x28f9e0)
sql3::Statement::~Statement(this=0x28f9e0, __in_chrg=<optimized out>) 
sql3::createDatabaseFromFile(db=..., commandFile=..., dbName=0x51e057 "Ressources\\DatabaseFile.txt", err=0x533cc0, multilineQueries=true)

这是析构函数的代码:

void sql3::Statement::erase()
{
    if (p_stmt)
    testCode(sqlite3_finalize(p_stmt), USING_INCORRECT_STATEMENT, nullptr, std::cerr);
        //testCode is a const function, so the above is equivalent to :

    if (p_stmt)
    sqlite3_finalize(p_stmt);

    p_stmt = nullptr;
}

sql3::Statement::~Statement()
{
    erase();
}

另外,不确定这是什么意思,但如果我在Statement :: makeAllSteps()之后调用Statement :: erase(),我就不会有任何错误。编辑:显然,这意味着由于某种原因跳过while(start_query!= std :: string :: npos&amp;&amp;!noError)循环。

编辑2:发现它,因为!noError。我被允许时会发布答案。

1 个答案:

答案 0 :(得分:0)

未来的亲人,这里是我的目标:

我的代码中存在两个问题。第一个就是那条线:

while (start_query != std::string::npos && !noError)

本应该是

while (start_query != std::string::npos && noError)

(在第一个中,noError开始为真,这意味着跳过循环)

我的项目中的第二个更普遍的问题是在sql3 :: Statement构造函数中:我忘了包含一行来将sqlite3_stmt指针设置为nullptr。

基本上,如果指针没有初始化为nullptr或初始化函数,那么调用finalize的唯一方法就是返回段错误。