C++ MongoDB C++;Qt应用程序中的驱动程序稳定分支崩溃
我正在使用Qt5.7.0和MSVC2015 64位编译器开发一个web应用程序。我使用QtCreator作为IDE。我成功地构建了mongoc、mongocxx和bsoncxx库,并将它们与系统链接起来。这些库是在发布模式下构建的,使用与QtWeb应用程序相同的编译器和运行时。我使用了C驱动程序的版本1.9,以及稳定的C++驱动程序的版本3.1。驱动程序是根据MongoDB提供的说明和标准设置构建的。我只将这两个驱动程序的发布版本链接到我的应用程序 在我的应用程序的调试构建中,一切正常。但是,在web应用程序的发布版本中,我设法在应用程序的主线程中创建了一个实例和连接池,但当我试图在子线程中从该池获取连接时,系统崩溃。下面的代码示例中指出了碰撞的确切位置 我不确定这是驱动程序还是我的多线程代码中的错误,因此我在下面包含了相关的代码片段。MongoPool对象是在主线程中创建的。当接收到新的用户请求时,将在子线程中创建MongoConnector对象。请注意,我尽可能地按照评论中的要求最小化了代码。任何人谁希望收到完整的申请代码,请与我联系,我将很高兴提供给你 main.cppC++ MongoDB C++;Qt应用程序中的驱动程序稳定分支崩溃,c++,multithreading,mongodb,qt,mongo-cxx-driver,C++,Multithreading,Mongodb,Qt,Mongo Cxx Driver,我正在使用Qt5.7.0和MSVC2015 64位编译器开发一个web应用程序。我使用QtCreator作为IDE。我成功地构建了mongoc、mongocxx和bsoncxx库,并将它们与系统链接起来。这些库是在发布模式下构建的,使用与QtWeb应用程序相同的编译器和运行时。我使用了C驱动程序的版本1.9,以及稳定的C++驱动程序的版本3.1。驱动程序是根据MongoDB提供的说明和标准设置构建的。我只将这两个驱动程序的发布版本链接到我的应用程序 在我的应用程序的调试构建中,一切正常。但是,在
#include "mongopool.h"
MongoPool *pool;
int main(int argc, char *argv[])
{
QCoreApplication app(argc,argv);
// Initialize MongoDB
pool = new MongoPool();
app.exec();
}
#包括“mongopol.h”
Mongopol::Mongopol()
{
使用bsoncxx::builder::stream::document;
自动uri=mongocxx::uri{mongocxx::uri::k_default_uri};
配置(std::move(uri));
试一试{
mongocxx::pool::entry client=get_connection();
自动管理=客户端->数据库(“管理”);
文件管理员;
ismaster查看stacktrace图像和mongocxx驱动程序代码后,以下代码仅打印“无连接”,但如果客户端无效,则不会返回false(或断言或退出),这是您应该做的
if(!client)
{
std::cout << "No Connection!";
}
if(!客户端)
{
std::cout数据库(dbName.toLatin1().toStdString());
如果客户端
是无效指针,则会发生崩溃
此外,根据示例(第35行)
最好把它写成
mongocxx::database dataDB=(*client)[dbName.toLatin1().toStdString()];
我在条件if块中添加了return语句,但这并没有解决问题,因为“无连接”的打印字符串和返回语句永远不会执行…执行总是跳过条件if块
我还修改了数据库请求行代码,但结果保持不变
问题仍然存在,为什么从池中获取的客户端在子线程中不可用
编辑:
今天,我设法发现问题与将Qt中使用的类型转换为MongoDB驱动程序中使用的类型有关
当我替换以下代码行时:
mongocxx::database dataDB = client->database(dbName.toLatin1().toStdString());
mongocxx::collection dataCollection = dataDB[collectionName.toLatin1().toStdString()];
通过以下代码行,一切正常:
mongocxx::database dataDB = client->database("testdb");
mongocxx::collection dataCollection = dataDB["testcollection"];
我尝试用几种方式将QString转换为驱动方法调用的参数,但还没有使它工作。任何人都知道如何将QStand变量转换成MangoDB C++驱动程序的参数? < P>最后,我设法获得了获取数据库和集合工作的代码。文档的插入现在可以在调试和发布模式下工作。我知道我的解决方案可能并不完美,但至少它解决了这部分问题。我检查了mongo shell,插入确实正确执行
auto dbNameString = dbName.toStdString();
auto collectionNameString = collectionName.toStdString();
char *dbNameArray = new char[dbNameString.length()+1];
for(int i=0; i<dbNameString.length(); i++)
{
dbNameArray[i] = dbNameString.at(i);
}
dbNameArray[dbNameString.length()] = '\0';
char *collectionArray = new char[collectionNameString.length()+1];
for(int i=0; i<collectionNameString.length(); i++)
{
collectionArray[i] = collectionNameString.at(i);
}
collectionArray[collectionNameString.length()] = '\0';
mongocxx::database dataDB = client->database(dbNameArray);
mongocxx::collection dataCollection = dataDB[collectionArray];
std::string docDB = doc.toLatin1().toStdString();
bsoncxx::document::value obj = bsoncxx::from_json(docDB.c_str());
std::string id = docID.toStdString();
auto builder = bsoncxx::builder::stream::document{};
bsoncxx::document::value doc_value = builder
<< "_id" << id.c_str()
<< "doc" << obj
<< bsoncxx::builder::stream::finalize;
bsoncxx::document::view view = doc_value.view();
auto insert_result = dataCollection.insert_one(view);
auto-dbNameString=dbName.toStdString();
auto collectionNameString=collectionName.TostString();
char*dbNameArray=new char[dbNameString.length()+1];
对于(int i=0;iIs此池和其他对象线程安全,可以这样使用吗?您可以共享堆栈跟踪吗?为什么要包装mongocxx类?请将此编辑为一个,没有人会阅读这么多代码。我想您也在mongodb开发中问过这个问题。我同意上面的评论:提供堆栈跟踪、驱动程序版本,以及ild有关驱动程序的信息,并使用工具链提供的诊断工具来查找未定义的行为、内存错误和数据竞争。上述要求的MCVE也更可能揭示问题。我同意,这似乎是最有可能的解释。无法从“stacktrace”中确知用户发布(为什么人们坚持发布截图?)。如果客户端指针为空,则在调试器中应该很明显。@acm-hmm,不确定op发布屏幕截图的原因,我只是在寻找StackTrace。我在您的代码中看不到任何与线程有关的内容。请根据此线程中的几个请求,将其拆分为一个最小的可编译示例。理想情况下,不涉及QT。@acm I e编辑上面的帖子以反映我的最新发现。这是足够的信息还是我需要提供更多的细节?嗯。我有一个想法,这与临时变量的生存期和视图或值
参数类型有关。也许绑定没有按预期工作。我不熟悉QString
,但可以尝试捕获使用auto dbStr=dbNAme.toLatin1().toStdString()
转换为std::string
,然后在调用中将其移动到database
的结果,如client->database(std::move(dbStr))
。对传递给database::operator[]
。这解决了您的问题吗?如果是这样,我将深入了解QString
到std::string
在呼叫站点的绑定情况。@acm今天我尝试了您的建议,但当我按照您在命令中的建议编写代码时,仍然会出现相同的崩溃
if(!client)
{
std::cout << "No Connection!";
}
mongocxx::database dataDB = client->database(dbName.toLatin1().toStdString());
mongocxx::collection dataCollection = dataDB[collectionName.toLatin1().toStdString()];
mongocxx::database dataDB = client->database("testdb");
mongocxx::collection dataCollection = dataDB["testcollection"];
auto dbNameString = dbName.toStdString();
auto collectionNameString = collectionName.toStdString();
char *dbNameArray = new char[dbNameString.length()+1];
for(int i=0; i<dbNameString.length(); i++)
{
dbNameArray[i] = dbNameString.at(i);
}
dbNameArray[dbNameString.length()] = '\0';
char *collectionArray = new char[collectionNameString.length()+1];
for(int i=0; i<collectionNameString.length(); i++)
{
collectionArray[i] = collectionNameString.at(i);
}
collectionArray[collectionNameString.length()] = '\0';
mongocxx::database dataDB = client->database(dbNameArray);
mongocxx::collection dataCollection = dataDB[collectionArray];
std::string docDB = doc.toLatin1().toStdString();
bsoncxx::document::value obj = bsoncxx::from_json(docDB.c_str());
std::string id = docID.toStdString();
auto builder = bsoncxx::builder::stream::document{};
bsoncxx::document::value doc_value = builder
<< "_id" << id.c_str()
<< "doc" << obj
<< bsoncxx::builder::stream::finalize;
bsoncxx::document::view view = doc_value.view();
auto insert_result = dataCollection.insert_one(view);
auto builder = bsoncxx::builder::stream::document{};
bsoncxx::document::value doc_value = builder
<< "_id" << id.c_str()
<< bsoncxx::builder::stream::finalize;
bsoncxx::document::view view = doc_value.view();
bsoncxx::stdx::optional<bsoncxx::document::value> maybe_result =
dataCollection.find_one(view);
if(maybe_result)
{
// HERE THE CRASH HAPPENS
std::cout << bsoncxx::to_json(*maybe_result) << "\n";
}