C SQLite SQLite_静态局部变量问题
我正在查看一些供应商代码,有这样一个查询:C SQLite SQLite_静态局部变量问题,c,sqlite,dangling-pointer,C,Sqlite,Dangling Pointer,我正在查看一些供应商代码,有这样一个查询: BOOL BindQuery(sqlite3_stmt* stmt, PARAMS* params) { char temp[150] = ""; char paramBuf[10] = ""; if (currStmt == NULL) return FALSE; sprintf(paramBuf, "%d", (int)params->someParam); strcpy(temp, "%");
BOOL BindQuery(sqlite3_stmt* stmt, PARAMS* params)
{
char temp[150] = "";
char paramBuf[10] = "";
if (currStmt == NULL) return FALSE;
sprintf(paramBuf, "%d", (int)params->someParam);
strcpy(temp, "%");
strcat(temp, tempVolt);
strcat(temp, "%");
sqlite3_bind_text(stmt, 4, temp, strlen(temp), SQLITE_STATIC);
return TRUE;
}
之后,查询将被执行。问题是这个查询永远不会匹配,即使它应该匹配
我认为问题在于sqlite3\u bind\u text
绑定了一个局部变量,而SQLite保留了指向原始局部变量的指针。因此,当它超出范围时,它可能已经被覆盖。修复方法似乎是使用SQLITE\u TRANSIENT
。有人能证实我的想法吗?还是我偏离了基地
另一个奇怪的问题是,供应商从未能够复制它。运气好吗?是的,这个代码是错误的。报告说: 如果第五个参数是特殊值SQLITE_STATIC,则SQLITE假定信息位于静态的非托管空间中 但这个局部变量不是静态的
如果堆栈的该部分在执行查询之前避免被覆盖,则此代码可能会工作。如果有人在sqlite
C
ABI上创建一个现代的C++
包装器,则
我们可以使用一个R值引用来选择性地使用SQL\u
对于传递的临时对象
像下面这样
class Statement
{
/*Other Logic*/
/* Other Bind() overloads using SQLITE_STATIC */
void Bind(const int index, std::string && text) const
{
if(SQLITE_OK != sqlite3_bind_text(FetchABI(),index,text.c_str(),text.size(),SQLITE_TRANSIENT))
{
// Error Handling
}
}
/* Bind overload for std::wstring */
};
当我们传递一个临时对象时,编译器足够聪明,可以选择正确的重载,因此我们避免了SQLite在每个地方都制作私有副本的成本(对于小型应用程序可能不需要这样做)
内干管()
注意:FetchABI()获取底层句柄,其实现取决于某人的突发奇想 “如果第五个参数的值为SQLITE_TRANSIENT,那么SQLITE会在sqlite3_bind_*()例程返回之前立即创建自己的数据私有副本。”听起来您是对的。
Statement obj;
obj.Prepare(cx,"Select ?1"); // cx is the connection not defined here for brevity
obj.Bind(1,std::string("This value is copied"));
// Or the second overload
obj.Bind(1,std::wstring(L"This too is copied"));