我试图使用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。我被允许时会发布答案。
答案 0 :(得分:0)
未来的亲人,这里是我的目标:
我的代码中存在两个问题。第一个就是那条线:
while (start_query != std::string::npos && !noError)
本应该是
while (start_query != std::string::npos && noError)
(在第一个中,noError开始为真,这意味着跳过循环)
我的项目中的第二个更普遍的问题是在sql3 :: Statement构造函数中:我忘了包含一行来将sqlite3_stmt指针设置为nullptr。
基本上,如果指针没有初始化为nullptr或初始化函数,那么调用finalize的唯一方法就是返回段错误。