C++ MongoDB C++;Qt应用程序中的驱动程序稳定分支崩溃

C++ 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提供的说明和标准设置构建的。我只将这两个驱动程序的发布版本链接到我的应用程序 在我的应用程序的调试构建中,一切正常。但是,在

我正在使用Qt5.7.0和MSVC2015 64位编译器开发一个web应用程序。我使用QtCreator作为IDE。我成功地构建了mongoc、mongocxx和bsoncxx库,并将它们与系统链接起来。这些库是在发布模式下构建的,使用与QtWeb应用程序相同的编译器和运行时。我使用了C驱动程序的版本1.9,以及稳定的C++驱动程序的版本3.1。驱动程序是根据MongoDB提供的说明和标准设置构建的。我只将这两个驱动程序的发布版本链接到我的应用程序

在我的应用程序的调试构建中,一切正常。但是,在web应用程序的发布版本中,我设法在应用程序的主线程中创建了一个实例和连接池,但当我试图在子线程中从该池获取连接时,系统崩溃。下面的代码示例中指出了碰撞的确切位置

我不确定这是驱动程序还是我的多线程代码中的错误,因此我在下面包含了相关的代码片段。MongoPool对象是在主线程中创建的。当接收到新的用户请求时,将在子线程中创建MongoConnector对象。请注意,我尽可能地按照评论中的要求最小化了代码。任何人谁希望收到完整的申请代码,请与我联系,我将很高兴提供给你

main.cpp

#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";
    }