多线程SQLite崩溃

6

我正在尝试在一个多线程的C++程序中使用SQLite 3.7.5。我已经将问题缩小到了几行简单的代码:

sqlite3 *Database;
sqlite3_stmt *Stmt;

int retval=sqlite3_open("database.db3",&Database);
retVal=sqlite3_prepare(&Database,"CREATE TABLE RawData (Key CHAR(5))",-1,&Stmt,0);
retval=sqlite3_step(Stmt);
retval=sqlite3_finalize(Stmt);

当我从主进程直接调用这段代码时,它可以正常工作。但是,如果我使用CreateThread()来创建一个线程:
unsigned long ThreadId;
CreateThread(0,0,(LPTHREAD_START_ROUTINE) InserterThread,&Info,0,&ThreadId);

sqlite3_step 调用中,我收到了 "buffer overrun" 的 Visual Studio 消息。如果我调试,我会看到崩溃位置在 dbghook.c 的 _CRT_DEBUGGER_HOOK 中。

我正在使用多线程静态 VC 库,并使用以下定义进行编译:

SQLITE_THREADSAFE=2
THREADSAFE=2

我已经通过 sqlite3_threadsafe() 进行了验证。

我可以追踪一点 SQLite 3 代码,但我希望有人能够发现我的代码中的明显问题并帮我避免麻烦。


如果您已经解决了问题,请发布一个包含解决方案的答案,以供其他人参考。 - chacham15
我从未找到问题的真正原因。我想我最终将项目减少到最小,问题就消失了。然后我逐渐添加组件,打算最终找到触发问题的组件,但我成功地添加了所有组件而问题没有再次出现。所以这是一个谜团... - Marc Bernier
1个回答

3

似乎 SQLITE_THREADSAFE 宏定义是用于编译,它并不会强制库使用该行为,只是使其可用。

仍需告知 sqlite 您希望使用多线程行为,可以在启动数据库时或运行时进行设置。

选择线程模式的启动时间

假设编译时的线程模式不是单线程,则可以使用sqlite3_config()接口在初始化期间更改线程模式。SQLITE_CONFIG_SINGLETHREAD将SQLite置于单线程模式,SQLITE_CONFIG_MULTITHREAD设置多线程模式,而SQLITE_CONFIG_SERIALIZED则设置序列化模式。

运行时选择线程模式

如果未在编译时或启动时选择单线程模式,则可以创建单个数据库连接作为多线程或序列化。无法将单个数据库连接降级为单线程模式。如果编译时或启动时模式是单线程,则也无法升级单个数据库连接。

单个数据库连接的线程模式由作为sqlite3_open_v2()的第三个参数给出的标志确定。SQLITE_OPEN_NOMUTEX标志使数据库连接处于多线程模式,而SQLITE_OPEN_FULLMUTEX标志使连接处于序列化模式。如果未指定任何标志,或者使用sqlite3_open()或sqlite3_open16()而不是sqlite3_open_v2(),则使用编译时和启动时设置确定的默认模式。

参考自http://www.sqlite.org/threadsafe.html


没有运气。我尝试了 sqlite3_config(SQLITE_CONFIG_MULTITHREAD); 还有使用带有 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX 的 sqlite3_open_v2。问题依旧。 - Marc Bernier
我已经编写了该问题的独立版本,并没有看到该问题。这是一个相当大的项目,我将逐步添加组件,直到问题再次出现。无论如何,还是谢谢。 - Marc Bernier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接