Error building mongoDB c++ driver application in Release mode

Building application in Release mode in Visual Studio 2022 fails.
Followed this tutorial Getting Started with MongoDB and C++ | MongoDB

Works great for Debug x64 mode, but switching it to Release mode fails(i have changed the project settings for release mode, just like it was done for Debug mode in that tutorial)
Running gives an A breakpoint instruction Error
Error:

Critical error detected c0000374
A breakpoint instruction (__debugbreak() statement or a similar call) was executed in mongoDBReleaseTesting.exe.

The program '[20728] mongoDBReleaseTesting.exe' has exited with code 0 (0x0).

Visual Studio shows error in xmemory file

File: C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\include\xmemory
Line: 255

Hi Abhay,

If you have updated all the config for release mode, I reckon the code in the shared tutorial should work fine.
Have you changed the code being executed? Can you share the callstack & code?

No i havent changed the code.
Although at first the provided code(connection to database) didnt even ran for Debug as well, error was

No suitable servers found (`serverSelectionTryOnce` set): [Server closed connection. [Server closed connection. calling hello on ac-3***]: genetic server error.

Followed this Fatal error building C++ drivers with VS 2022 under Win10 - are errors OK? - #2 by david_d
Did some tinkering and it worked.

Heres the code that currently works in Debug x64 mode.

#include <mongocxx/client.hpp>
#include <bsoncxx/builder/stream/document.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/uri.hpp>
#include <mongocxx/instance.hpp>
#include <algorithm>
#include <iostream>
#include <vector>
#include <mongocxx/exception/operation_exception.hpp>

using namespace std;

static const mongocxx::uri mongoURI("mongodb+srv://<userName>:<password>@<dbName>.kobcgfr.mongodb.net/?retryWrites=true&w=majority");
// Get all the databases from a given client.
vector<string> getDatabases(mongocxx::client& client)
{
		vector<string> cldn = client.list_database_names();
		return cldn;
	}
int main()
{
	// Create an instance.

	mongocxx::instance inst{};
	mongocxx::options::client client_options;
	auto api = mongocxx::options::server_api{ mongocxx::options::server_api::version::k_version_1 };
	client_options.server_api_opts(api);
	mongocxx::client conn{ mongoURI, client_options };

	cout << "password: " << conn.uri().password() << std::endl;
	cout << "username: " << conn.uri().username() << std::endl;
	cout << "auth_source: " << conn.uri().auth_source() << std::endl;

	auto dbs = getDatabases(conn);
	for (auto& db : dbs)
	{
		cout << db << endl;
	}
	cin.get();
	return 0;
}

Heres the call stack :

ntdll.dll!00007ffc38aef3d2()
ntdll.dll!00007ffc38af8192()
ntdll.dll!00007ffc38af847a()
ntdll.dll!00007ffc38afe101()
ntdll.dll!00007ffc38a97482()
ntdll.dll!00007ffc38a147b1()
ucrtbase.dll!00007ffc3663f05b()
[Inline Frame] mongoDBReleaseTesting.exe!std::_Deallocate(void * _Ptr, unsigned __int64 _Bytes) Line 255
	at C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\include\xmemory(255)
[Inline Frame] mongoDBReleaseTesting.exe!std::allocator<char>::deallocate(char * const _Count, const unsigned __int64) Line 829
	at C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\include\xmemory(829)
[Inline Frame] mongoDBReleaseTesting.exe!std::string::_Tidy_deallocate() Line 5019
	at C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\include\xstring(5019)
[Inline Frame] mongoDBReleaseTesting.exe!std::string::{dtor}() Line 3270
	at C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\include\xstring(3270)
mongoDBReleaseTesting.exe!main() Line 49
	at D:\WorkSpace\VisualStudio2017\Projects\c++ playground\mongoDBReleaseTesting\mongoDBReleaseTesting.cpp(49)
[External Code]

This seems like a config issue, given that debug mode works for you. This code should work (I tried it locally).

Can you try comparing the config you set for debug and release? You should be able to find the config file if you go to the folder where your solution is saved - and look for .vcxproj file. You can open it in a text editor and compare the release vs debug config.
Also ensure that you’re rebuilding the code.

Hey sorry couldn’t get back to you early.
Although i tried what you said(checked again, did the whole process again)…but it didnt work atleast for my project which i made just to test the release mode.
For my project where i actually want to use mongoDB. I did check the config files of it, did the process again, and it worked, atleast the project ran in the release mode…but only for few seconds. It failed in my mongoDB handler class. The instance of mongoDB is being created using a singleton class(as i want to use this handler class in various different places and want to see if the instance is already created or not).

The error happens on line 7 of MongoDB.cpp file
conn = mongocxx::client(mongoURI, client_options);
Error says :
1. A breakpoint instruction (__debugbreak() statement or a similar call) was executed in Project.exe.
2. Exception thrown at 0x00007FFCBF916F95 (ntdll.dll) in Project.exe: 0xC0000005: Access violation reading location 0x0000000000000000.
3. Unhandled exception at 0x00007FFCBF96F449 (ntdll.dll) in Project.exe: 0xC0000374: A heap has been corrupted (parameters: 0x00007FFCBF9D97F0).

MongoDB.h file

#pragma once

#include <cstdint>
#include <string>
#include <iostream>
#include "../Header Files/Config.h"

#include "bsoncxx/builder/stream/document.hpp"
#include "bsoncxx/json.hpp"
#include "bsoncxx/oid.hpp"
#include "mongocxx/client.hpp"
#include "mongocxx/database.hpp"
#include "mongocxx/uri.hpp"
#include <mongocxx/exception/operation_exception.hpp>

namespace learning {
	const mongocxx::uri mongoURI(mongodb_uri);
	const std::string dbName = databaseName;
	const std::string collName = colectionName;
	class MongoDB {
	public:
		MongoDB();
		void insertDocument(const bsoncxx::document::value document);		
		std::tuple<std::string, std::string, std::string> findDocument(const std::string& value);
		bool isDataPresent(const std::string& key, const std::string& value);
		int findScore(const std::string& value);
		void updateDocument(const std::string& key, const int& value, const std::string& newKey, const int& newValue);
		std::vector<std::pair<std::string, int>> getTopScores(int limit);				
	private:
		mongocxx::options::client client_options;
		mongocxx::options::server_api api;
		mongocxx::client conn;
		mongocxx::v_noabi::database ammpedUPDB;
		mongocxx::v_noabi::collection loginInfoCollection;
	};
}

MongoDB.cpp file

#include "../Header Files/MongoDB.h"

learning::MongoDB::MongoDB() :
	api(mongocxx::options::server_api::version::k_version_1)
{
	client_options.server_api_opts(api);
	conn = mongocxx::client(mongoURI, client_options);
	ammpedUPDB = conn.database(dbName);
	loginInfoCollection = ammpedUPDB.collection(collName);
}

void learning::MongoDB::insertDocument(const bsoncxx::document::value document)
{
	loginInfoCollection.insert_one(document.view());
}

std::tuple<std::string, std::string, std::string> learning::MongoDB::findDocument(const std::string& value)
{
	std::string key;
	if (value.find('@') != std::string::npos) {
		// Contains '@' symbol, so it looks like an email
		key = "email";
	}
	else {
		// Doesn't contain '@', so it looks like a username
		key = "username";
	}
	auto filter = bsoncxx::builder::stream::document{} << key << value << bsoncxx::builder::stream::finalize;
	// Add query filter argument in find
	auto cursor = loginInfoCollection.find({ filter });

	if (cursor.begin() == cursor.end()) {
		return  { "", "", "" };; // No data found
	}

	// Extract the first document from the cursor
	auto document = *cursor.begin();

	// Extract the individual components of the retrieved data
	std::string retrievedUsername = std::string(document["username"].get_string().value);
	std::string retrievedEmail = std::string(document["email"].get_string().value);
	std::string retrievedPassword = std::string(document["pwd"].get_string().value);

	return  { retrievedUsername, retrievedEmail, retrievedPassword };
}

bool learning::MongoDB::isDataPresent(const std::string& key, const std::string& value)
{
	// Create the query filter
	auto filter = bsoncxx::builder::stream::document{} << key << value << bsoncxx::builder::stream::finalize;
	// Add query filter argument in find
	auto cursor = loginInfoCollection.find({ filter });
	return (cursor.begin() != cursor.end());
}

int learning::MongoDB::findScore(const std::string& value)
{
	auto filter = bsoncxx::builder::stream::document{} << "username" << value << bsoncxx::builder::stream::finalize;
	mongocxx::options::find opts;
	opts.projection(bsoncxx::builder::basic::make_document(bsoncxx::builder::basic::kvp("score", 1)));
	auto cursor = loginInfoCollection.find({ filter }, opts);
	for (auto&& doc : cursor)
	{
		bsoncxx::document::element curvename = doc["score"];
		int score = curvename.get_int32().value;
		return score;
	}
}

void learning::MongoDB::updateDocument(const std::string& key, const int& value, const std::string& newKey, const int& newValue)
{
	loginInfoCollection.update_one(bsoncxx::builder::stream::document{} << key << value << bsoncxx::builder::stream::finalize,
		bsoncxx::builder::stream::document{} << "$set" << bsoncxx::builder::stream::open_document << newKey << newValue << bsoncxx::builder::stream::close_document << bsoncxx::builder::stream::finalize);
}

std::vector<std::pair<std::string, int>> learning::MongoDB::getTopScores(int limit)
{
	std::vector<std::pair<std::string, int>> topScores;
	mongocxx::options::find opts;
	opts.sort(bsoncxx::builder::basic::make_document(
		bsoncxx::builder::basic::kvp("score", -1)));
	opts.limit(limit);
	auto cursor = loginInfoCollection.find({}, opts);
	for (auto&& doc : cursor) {
		std::string username = std::string(doc["username"].get_string().value);
		int score = doc["score"].get_int32().value;

		topScores.emplace_back(username, score);
	}
	return topScores;
}

I could reproduce the problem. I suspect the singleton implementation may not be working correctly.

Hypothesis:

  • The problem seems to occurring because the constructor MongoDB() is getting called multiple times. It works fine for the first time but for the second iteration it will throw an exception because the code tries to recreate the existing connection.
  • This may be the reason why your code works fine for first few seconds, ie. first call goes fine but successive calls won’t.

Suggestions

  • Wrap the constructor in try block and catch and check the exception thrown (See example in https://www.mongodb.com/docs/drivers/cxx/ ).
  • Check if singleton is implemented properly. You can put a breakpoint in the constructor to validate it should be called only once it the lifetime of your code.

Ok i think i had some problem with the singleton class. I fixed it.
And i added the try and catch block as per shown in the link attached.
Now the error appears on line

ammpedUPDB = conn.database(dbName);
error :

  1. Exception thrown at 0x00007FF84ABE1340 (vcruntime140d.dll) in project.exe: 0xC0000005: Access violation reading location 0x0000000000424470.
  2. Unhandled exception at 0x00007FF84ABE1340 (vcruntime140d.dll) in project.exe: 0xC0000005: Access violation reading location 0x0000000000424470.

Here’s the call stack if you need it

 	vcruntime140d.dll!00007ff84ba51340()	Unknown
 	bsoncxx.dll!00007ff83c351798()	Unknown
 	bsoncxx.dll!00007ff83c349077()	Unknown
 	bsoncxx.dll!00007ff83c34aefc()	Unknown
 	bsoncxx.dll!00007ff83c34a873()	Unknown
 	bsoncxx.dll!00007ff83c354e17()	Unknown
 	mongocxx.dll!00007ffff0a1f7aa()	Unknown
 	mongocxx.dll!00007ffff0a6ed53()	Unknown
>	project.exe!learning::MongoDB::MongoDB() Line 23	C++
 	project.exe!LoginPageState::LoginPageState(std::shared_ptr<Context> & context) Line 7	C++
 	project.exe!LoginState::update(sf::Time deltaTime) Line 168	C++
 	project.exe!main() Line 6	C++
 	[External Code]	

For reference here is the singleton class
MongoInstanceManager.h

#pragma once
#include <mongocxx/instance.hpp>
class MongoInstance {
private:
    static MongoInstance* m_instance;
    mongocxx::instance instance;
    // Private constructor
    MongoInstance();
public:
    // Deleted copy constructor and assignment operator to enforce singleton
    MongoInstance(const MongoInstance&) = delete;
    MongoInstance& operator=(const MongoInstance&) = delete;
    ~MongoInstance();
    static MongoInstance* getInstance();
};

MongoInstanceManager.cpp

#include "../Header Files/MongoInstanceManager.h"
MongoInstance* MongoInstance::m_instance = nullptr;
MongoInstance::MongoInstance() : instance() {}
MongoInstance::~MongoInstance() {}
MongoInstance* MongoInstance::getInstance() {
    if (!m_instance) {
        if (!m_instance) {
            m_instance = new MongoInstance;
        }
    }
    return m_instance;
}

For people stumbling across this.
The tutorial has be updated with the additional cmake flags for the c++ driver build
which fixes the debug and release error. (Tutorial)
For the database connection error, make sure to use the std::string_view for the database string name
and also use the appropriate constructor explicitly.

const std::string_view dbName = "StudentRecords";
const std::string_view collName = "StudentRecords";
conn = mongocxx::client(mongoURI, client_options);
database = conn.database(bsoncxx::string::view_or_value(dbName));
collection = database.collection(bsoncxx::string::view_or_value(collName));

Doing this fixed the errors i got.

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.