sqlite3_column_text返回unsigned char*乱码导致比对失败如何解决
问题产生原因
- 核心原因1:
sqlite3_column_text()返回的指针生命周期和预处理语句对象stmt完全绑定,你在读取返回值后直接调用了sqlite3_finalize(stmt)销毁了stmt,此时result指针指向的内存已经被SQLite释放,后续访问属于野指针访问,自然会出现乱码、无效值。 - 核心原因2:你用
==比较两个unsigned char*类型的变量,本质是比较两个指针指向的内存地址,而不是指针指向的字符串内容。就算两个指针指向的字符串完全相同,只要存储地址不同,比较结果永远是false。 - 额外隐藏问题:你没有判断
sqlite3_step()的返回值是否为SQLITE_ROW,如果查询没有命中任何行,sqlite3_column_text()会直接返回NULL,也会导致后续访问异常;另外你直接拼接SQL语句存在SQL注入风险,且函数声明为void返回类型却写了return -1属于语法错误,输出语句还漏写了引号闭合符。
修复方案
你只需要在销毁stmt之前把查询到的字符串拷贝到自己管理的内存中,再用标准字符串比较方法比对即可,修改后的参考代码如下:
// 函数返回值改成bool更合理,用来返回是否匹配 bool check_username(std::string username) { sqlite3_stmt* stmt; // 不要直接拼接SQL,用参数绑定避免注入,先写带占位符的SQL const char* query = "SELECT username FROM bank_account WHERE username = ?;"; int rc = sqlite3_prepare_v2(DB, query, -1, &stmt, NULL); if (rc != SQLITE_OK) { std::cerr << "Error: " << sqlite3_errmsg(DB) << std::endl; sqlite3_finalize(stmt); return false; } // 绑定参数,第1个参数下标是1,绑定字符串内容 sqlite3_bind_text(stmt, 1, username.c_str(), -1, SQLITE_STATIC); rc = sqlite3_step(stmt); bool is_match = false; // 先判断是否查询到了结果行 if (rc == SQLITE_ROW) { // 在销毁stmt前直接把结果转成std::string,拷贝内容到自己的变量里 const char* result = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)); std::string result_str(result); // 直接用std::string的==比较内容即可 is_match = (result_str == username); } // 用完再销毁stmt sqlite3_finalize(stmt); if (is_match) std::cout << "It's match!" << std::endl; else std::cout << "It's not match!" << std::endl; return is_match; }
内容的提问来源于stack exchange,提问作者Kevin Mahendra
相关产品推荐
相关产品推荐

