C++-SQLite3在多线程环境中泄漏句柄

C++ - SQLite3 leaks handles in multithread environment

本文关键字:泄漏 句柄 环境 多线程 C++-SQLite3      更新时间:2023-10-16

我写了一个简单的程序,它产生了10个线程,每个线程打开一个数据库(所有线程都公用),或者如果打开失败,则创建它(使用"预写日志"选项),在数据库上创建一个表,然后进入一个无限循环,每次向表中添加一行。我发现程序每5分钟泄漏2个句柄,我尝试了一个名为Memory Verify的工具,该工具告诉我泄漏的句柄是SQLite3文件锁(版本3.7.13上的第34034行),但我不确定错误是在SQLite中还是在我使用它的方式中

我没有指定任何编译器选项来构建SQLite3,所以它是作为多线程构建的,据我所知,在我的情况下,多线程应该可以很好地工作,因为每个线程都有自己的SQLite连接。

要打开或创建数据库,我使用以下代码:

bool Create()
{
int iFlags = 0;
iFlags = iFlags | SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_CREATE;
return sqlite3_open_v2(dbName_sm.c_str(), &pHandle_m, iFlags, 0) == SQLITE_OK;
}
bool Open()
{
int iFlags = 0;
iFlags = iFlags | SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX;
return sqlite3_open_v2(dbName_sm.c_str(), &pHandle_m, iFlags, 0) == SQLITE_OK;
}

每个线程中的硬循环都会调用ExecuteQuery,它会准备、执行和完成INSERT语句:

bool ExecuteQuery(const std::string& statement)
{
bool res = Prepare(statement);
if(!res)
{
return false;;
}
SQLiteStatus status = Step();
Finalize();
res = (ESuccess == status || EDatabaseDone == status);
return res;
}
bool Prepare(const std::string& statement)
{
return sqlite3_prepare_v2(pHandle_m, statement.c_str(), -1, &pStmt_m, 0) == SQLITE_OK;
}
enum SQLiteStatus { ESuccess, EDatabaseDone, EDatabaseTimeout, EDatabaseError };
SQLiteStatus Step()
{
int iRet = sqlite3_step(pStmt_m);
if (iRet == SQLITE_DONE)
{
return EDatabaseDone;
}
else if (iRet == SQLITE_BUSY)
{
return EDatabaseTimeout;
}
else if (iRet != SQLITE_ROW)
{
return EDatabaseError;
}
return ESuccess;
}
bool Finalize()
{
int iRet = sqlite3_finalize(pStmt_m);
pStmt_m = 0;
return iRet == SQLITE_OK;
}

你们看到我的代码中有错误吗?或者这是SQLite中已知的问题吗?我试着用谷歌搜索了几天,但找不到任何关于它的信息。

非常感谢你的帮助。

问候,

Andrea

第页。S.我忘了说我在WinXP 64位PC上运行我的测试,编译器是VS2010,应用程序是用32位编译的,SQLite版本是3.7.13…

检查每个sqlite3_step之后是否有sqlite3_reset,因为这是一种可能导致泄漏的情况。在用sqlite3_prepare准备一个语句并用sqlite3-step执行它之后,您需要始终使用sqlite3_reset重置它。