首先,这是一个新手问题。我已经构建了一个基本的c ++包装类,用于在小项目的框架中与sqlite3
进行交互。这是它的一部分:
data_wrapper.hpp
#ifndef DATAWRAPPER_H
#define DATAWRAPPER_H
class DataWrapper
{
private:
sqlite3 *db_;
const char *db_file_;
int rc_;
bool prepare ( sqlite3_stmt* statement, const char* query );
bool check_table ( const char* table_name );
public:
DataWrapper ( const char* db_file );
sqlite3* get_database();
};
#endif // DATAWRAPPER_H
data_wrapper.cpp
#include <iostream>
#include <cstring>
#include "data_wrapper.hpp"
using namespace std;
DataWrapper::DataWrapper ( const char* db_file ) : db_ ( nullptr )
{
db_file_ = db_file;
}
sqlite3* DataWrapper::get_database()
{
return db_;
}
bool DataWrapper::prepare ( sqlite3_stmt* statement, const char* query )
{
cout << "preparing: " << query << endl;
rc_ = sqlite3_prepare_v2 ( db_, query, strlen ( query ), &statement, 0 );
cout << "statement is: " << &statement << endl;
return rc_ == SQLITE_OK;
}
/**
* Checks if a given table is present on the database
*
* @param table_name The name of the table to check.
* @return bool True if table exists, false otherwise.
*/
bool DataWrapper::check_table ( const char* table_name )
{
const char* query = "SELECT name FROM sqlite_master WHERE type='table' AND name=?;";
sqlite3_stmt* stmt = nullptr;
if ( !prepare ( stmt, query ) ) {
cout << "can't prepare query" << endl;
return false;
}
cout << "statement now is: " << stmt << endl;
if ( !bind ( stmt, 1, table_name ) ) {
return false;
}
step ( stmt );
return rc_ == SQLITE_ROW;
}
在某个地方,我有一个init
公共方法,它打开一个连接并检查是否存在给定的表。专家会看到问题,可以通过控制台输出来总结:
preparing: SELECT name FROM sqlite_master WHERE type='table' AND name=?;
done preparing
statement is: 0x7fff6bd121d0
statement now is: 0
不是sqlite3
的使用是问题的一部分(或者是吗?),但当然,我无法在NULL
语句上绑定任何内容:
(21) API called with NULL prepared statement
(21) misuse at line 76880 of [a65a62893c]
在prepare
范围结束后,您会看到我丢失了指针引用。我一直在寻找类似问题的堆栈,但没有一个正确地解决我的问题。那么如何防止这种情况,并且可能现代,
在学习曲线上,我不妨掌握实际的c ++ 11技术。
答案 0 :(得分:2)
bool DataWrapper::prepare ( sqlite3_stmt* statement, const char* query )
上面的函数按值statement
指针,所以当你像这样传递指针时指针:
rc_ = sqlite3_prepare_v2 ( db_, query, strlen ( query ), &statement, 0 );
您只是更新本地副本,而不是更新呼叫站点的副本。
简单的解决方法是通过引用获取指针:
bool DataWrapper::prepare ( sqlite3_stmt*& statement, const char* query )
答案 1 :(得分:2)
prepare
签名应为
bool DataWrapper::prepare ( sqlite3_stmt*& statement, const char* query )
注意为语句添加了&
。
传递指针参数时,复制其值(即地址)。在函数内更新此参数不会更改调用函数中的指针。
在更改函数之前添加&
以通过引用接收参数,这将使被调用函数内的任何更新更新调用函数的参数。