我目前正在开发一个使用数据库连接的小型C++程序。
它是通过CPPCONN连接器与MySQL数据库的连接。
原因
我正在使用多个线程,因此我创建了以下方法:
void Database::startThread()
{
fDriver->threadInit();
}
void Database::stopThread()
{
fDriver->threadEnd();
}
void Database::connect(const string & host, const string & user, const string & password, const string & database)
{
fDriver = sql::mysql::get_driver_instance();
fConnection.reset(fDriver->connect((SQLString)host,(SQLString)user,(SQLString)password));
fConnection->setSchema((SQLString) database);
fStatement.reset(fConnection->createStatement());
fConnection->setClientOption("multi-queries","true");
fConnection->setClientOption("multi-statements","true");
}
问题是我在fDriver-> threadInit()调用时遇到段错误。
我可以向您保证,通过连接功能可以正确实例化fDriver。
(fDriver也不为空)
崩溃
不幸的是,我无法提供更多有用的信息,但这是GDB的回溯记录:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff4d66700 (LWP 16786)]
0x0000000000414547 in Database::startThread (this=Unhandled dwarf expression opcode 0xf3
#0 0x0000000000414547 in Database::startThread (this=Unhandled dwarf expression opcode 0xf3) at src/core/database.cpp:73
#1 0x0000000000405443 in Parser::Parser (this=0x7ffff4d659b8) at src/core/sv_parse.cpp:11
#2 0x000000000041e76d in MessageProcessor::MessageProcessor (this=0x7ffff4d659b0, serverStartTime=...) at src/server/messageProcessor.cpp:12
#3 0x000000000041bae8 in Server::__lambda1::operator() (__closure=0x62c740) at src/server/server.cpp:89
#4 0x00007ffff763f550 in execute_native_thread_routine () at ../../../../../libstdc++-v3/src/c++11/thread.cc:84
#5 0x00007ffff6edb851 in start_thread () from /lib64/libpthread.so.0
#6 0x00007ffff6c2994d in clone () from /lib64/libc.so.6
备注
现在很奇怪的部分:这种崩溃不会一直发生!
有时它可以完美运行。
但是,如果不这样做,那当然是非常烦人的。
CPPCONN版本为1.1.3,而我们使用的是g++版本4.8.1。
我希望有人能揭开这个谜底!
吉里尔
最佳答案
我因同样神秘的分割错误而奋斗了几个小时。
我发现在get_driver_instance()周围添加互斥锁可以解决此问题。
这是线程函数的基本框架。这适用于从数据库中选择,可能不适用于插入或更新。
#include <mutex>
std::mutex mtx;
void test()
{
sql::Driver *driver;
sql::Connection *con;
try {
mtx.lock();
driver = get_driver_instance();
mtx.unlock();
driver->threadInit();
con = driver->connect(HOST, USER, PASS);
...
con->close();
driver->threadEnd();
} catch(...) { ... }
}