Unset document element in Mongo CXX - c++

I have a class that has a bsoncxx::document::view view as a private attribute, and a method that get a document from the Mongo database and save the result in the local bsoncxx::document::value value variable and then get the view from the value.view() and save it in the class bsoncxx::document::view view variable:
const bool User::search_one_by_id(const std::string &id = "")
{
// The prototype of the method below: const std::tuple<bool, bsoncxx::document::value> search_one_by_id(mongocxx::collection &, const std::string &) const;
auto status = Crud::search_one_by_id(this->collection, id);
if (std::get<0>(status))
{
// Error
return EXIT_FAILURE;
}
else
{
// Success
bsoncxx::document::value value = std::get<1>(status);
bsoncxx::document::view view = value.view();
this->view = view;
return EXIT_SUCCESS;
}
}
The problem is that if I get some element from the view in the method above, i.e the code below before the return EXIT_SUCCESS, no errors are issued.
bsoncxx::document::element element = this->view["first_name"];
std::cout << "First Name: " << element.get_utf8().value.to_string();
But if I get a view, save it in the bsoncxx::document::view view variable and try to get some element from the view in another class method:
void get_element()
{
bsoncxx::document::element element = this->view["first_name"];
std::cout << "First Name: " << element.get_utf8().value.to_string();
}
I receive the error:
terminate called after throwing an instance of 'bsoncxx::v_noabi::exception'
what(): unset document::element
Makefile:26: recipe for target 'run' failed
make: *** [run] Aborted (core dumped)
I had tried to use a pointer to save the reference to the view that I get in the search_one_by_id method. I had check if the type of the attribute (first_name) I'm getting is the right type to get the value of the element. I had check if the attribute exist in the document. I had tried to use the release() method from the view in the User::search_one_by_id. I had check if the view is empty through:
if (this->view.empty())
{
std::cout << "Empty: " << this->view.empty();
}
else
{
std::cout << "Loaded: " << this->view.empty() << " length " << this->view.length();
}
Inside the get_element method, and the output is:
# If I comment the call to search_one_by_id
$ Empty: 1
# If I enable the call to search_one_by_id
$ Loaded: 0 length 129
The GDB log to backtrace:
#0 __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007ffff6fd7801 in __GI_abort () at abort.c:79
#2 0x00007ffff762c957 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007ffff7632ab6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007ffff7632af1 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007ffff7632d24 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00007ffff793985c in bsoncxx::v_noabi::document::element::type() const () from /usr/local/lib/libbsoncxx.so._noabi
#7 0x00007ffff7939abc in bsoncxx::v_noabi::document::element::get_utf8() const () from /usr/local/lib/libbsoncxx.so._noabi
#8 0x0000555555559353 in User::get_element() ()
#9 0x0000555555556668 in main ()
Some tips ? The project can be found on Github
References:
Unset Document::element, MongoCXX Find Option Projection
Document value
Document view
Document element
document::element::operator[] overloads should not throw when given an invalid element
How do I get the type of a variable?

i think you need to keep the pointer to buffer of value somewhere. view object is pointing to deleted memory i suppose. try something like this
class User
{
bsoncxx::document::value _value; <<< store at class level
};
const bool User::search_one_by_id(const std::string &id = "")
{
// The prototype of the method below: const std::tuple<bool, bsoncxx::document::value> search_one_by_id(mongocxx::collection &, const std::string &) const;
auto status = Crud::search_one_by_id(this->collection, id);
if (std::get<0>(status))
{
// Error
return EXIT_FAILURE;
}
else
{
// Success
_value = std::get<1>(status);
this->view = _value.view();
return EXIT_SUCCESS;
}
}

Related

QAction::text(), Program received signal SIGSEGV, Segmentation fault

I working on migration of a product from QT4 to 5.
I am getting this error while backtracing it-
#0 0x00007ffff5488cd1 in QAction::text() const () from /fa/sw/registry/22851-export_qt5-04-soni-01/serverdist/dist/x86_linux/lib64/libQt5Widgets.so.5
#1 0x0000000000c17435 in cQ_ELEMENTS_COMBOBOX::AppendItem(QString const&) ()
#2 0x00000000005441e6 in cEXPORT_FILE_PARMS::initialize(QWidget*, cQ_GRID_LAYOUT*, int, bool, char const*) ()
#3 0x0000000000545ad3 in cEXPORT_FILE_PARMS::cEXPORT_FILE_PARMS(QWidget*, cGV_DEC_PROJECT*, ExportOutputFileParameterSet*, cQ_GRID_LAYOUT*, int, QString) ()
asINT32 cQ_ELEMENTS_COMBOBOX::AppendItem(const QString &item_name)
{
//if item already exists then do not append item
if(GetAction(m_popup_p, item_name) == NULL) {
m_popup_p->addAction(item_name);
return 0;
}
return -1;
}
QAction* GetAction(QMenu* menu, const QString& actionName){
QList<QAction*>::iterator menuItr = menu->actions().begin();
/*const*/ QList<QAction*>::iterator menuEnd = menu->actions().end();
while (menuItr != menuEnd)
{
if((*menuItr)->text() == actionName){
return *menuItr;
}
menuItr++;
}
return NULL;
}
After giving print statements on this line program crashes -
if((*menuItr)->text() == actionName)
sometimes it works and sometimes it crashes, not able to see a particular pattern. Is there any workaround or any way to catch the segmentation fault beforehand.

Do C++ vector and Gtkmm work together perfectly?. Segmentation fault when getting values of vector<string> from gtkmm on_click method

I am in middle of creating treeview for my project using gtkmm and C++.
What I want to do is to get variable properties from my order class. And I choose to use vector to store those properties so I get them easily by calling that method in the different class such as my main_window class. I can successfully get all values from other classes except main_window class showing segmentation fault.
To run my program:
1/ type "make" in terminal
2/ type "./mice" to run program
3/ click file->test. The program crashes
main_window.cpp class:
void Main_window::on_test_click() {
std::cout<< " On _test_clicked\n";
//auto add 1 order
controller.execute_cmd(99);
//THE LINE BELOW IS NOT WORKING IN ON_TEST_CLICK
std::vector<std::string> record = controller.order_to_strings(0);
}
auto_add method from emporium. cpp
void Emporium::auto_add() {
Order order0(1);
add_order(&order0);
std::vector<std::string> record = order_to_strings(0);
std::cout << "This is printing from emporium.cpp class" <<std::endl
<< "Id:" << record[0] <<"State: "<< record[1]<<"Price:"<< record[2]<< std::endl;
}
vector methods in emporium, order, controller classes.
std::vector<std::string> Controller::order_to_strings(int index) {
emporium.order_to_strings(index);
}
std::vector<std::string> Emporium::order_to_strings(int index) {
return orders[index]->to_strings();
}
std::vector<std::string> Order::to_strings(){
std::vector<std::string> order;
order.push_back(std::to_string(id_number));
order.push_back(state.to_string());
order.push_back(std::to_string(price));
return order;
}
Error:
*** Error in `./mice': free(): invalid pointer: 0x00007fa77a295000 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7fa77d63a7e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7fa77d64337a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7fa77d64753c]
./mice[0x406793]
./mice[0x4065cf]
./mice[0x40630a]
./mice[0x405eb7]
./mice(_ZNSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EED1Ev+0x35)[0x405b03]
......
This is my full version of my project. Test folder is my simplified version: https://github.com/dtn9797/MICE/tree/master/test
In the method auto_add(), Order object is created, which is destroyed in the end of auto_add() method. However in mean time pointer to this object is added to vector orders. This pointer point to invalid data in memory outside auto_add() method. Accessing data behind this pointer give crash.
void Emporium::auto_add() {
Order order0(1); //creating order0 local variable
add_order(&order0); //here pointer to something that will be destroyed soon is stored
std::vector<std::string> record = order_to_strings(0);
std::cout << "This is printing from emporium.cpp class" <<std::endl
<< "Id:" << record[0] <<"State: "<< record[1]<<"Price:"<< record[2]<< std::endl;
} //order0 local variable is destroyed here
void Emporium::add_order (Order* order) {
orders.push_back(order);
}
One of possible solution to prevent crash you can create Order object like this:
void Emporium::auto_add() {
add_order(new Order(1));
std::vector<std::string> record = order_to_strings(0);
std::cout << "This is printing from emporium.cpp class" <<std::endl
<< "Id:" << record[0] <<"State: "<< record[1]<<"Price:"<< record[2]<< std::endl;
}
But then for code correctness, remember to delete orders that are in std::vector<Order*> orders in the Emporium class destructor.

Modify value of attribute in XML C++

I am having a XML file as follows:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ConfigData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MyData>
<FrontCamera>2</FrontCamera>
<RearCamera>8</RearCamera>
</MyData>
</ConfigData>
I need to modify value of an attribute RearCamera from value 8 to 16.
I am using C++ and having libxml2 library
I have tried like below it was not working as expected. Were am i wrong?
xmlDoc* doc = NULL;
xmlNode* root_node = NULL;
xmlNode *child_node = NULL;
xmlNode *cur_node = NULL;
xmlNode *cur = NULL;
LIBXML_TEST_VERSION //!< Macro to check API for match with the DLL we are using
doc = xmlParseFile("ConfigFile.xml"); //!<parse the file and get the DOM
if ( doc == NULL)
{
}
else
{
root_node = xmlDocGetRootElement(doc);
if( root_node != NULL )
{
child_node = root_node->children;
unsigned char* cValue;
int iHandedness = 0;
while(child_node!=NULL)
{
if(!xmlStrcmp(child_node->name,(const xmlChar *)"MyData"))
{
cur = child_node->children;
if(NULL!= cur)
{
for (cur_node = cur; cur_node; cur_node = cur_node->next)
{
if (cur_node->type == XML_ELEMENT_NODE)
{
if(!xmlStrcmp(cur_node->name,(const xmlChar *)"RearCamera"))
{
cur_node->children->content = (const xmlChar *)(16) ;
}
}
}
}
}
child_node = child_node->next;
}
}
xmlSaveFormatFile ("ConfigFile.xml", doc, 1);
xmlFreeDoc(doc); //!< free document
xmlCleanupParser();
}
Save is not happening ,code dump is happening back trace :
n __vfprintf_chk () from /lib/libc.so.6
#1 0xb5bb7028 in xmlGenericErrorDefaultFunc () from /usr/lib/libxml2.so.2
#2 0xb5bb6e6b in xmlReportError () from /usr/lib/libxml2.so.2
#3 0xb5bb839e in __xmlRaiseError () from /usr/lib/libxml2.so.2
#4 0xb5bb8507 in __xmlSimpleError () from /usr/lib/libxml2.so.2
#5 0xb5be3f81 in __xmlIOErr () from /usr/lib/libxml2.so.2
#6 0xb5be43d7 in xmlIOErr () from /usr/lib/libxml2.so.2
#7 0xb5be4841 in xmlFileOpenW () from /usr/lib/libxml2.so.2
#8 0xb5be7369 in __xmlOutputBufferCreateFilename () from /usr/lib/libxml2.so.2
#9 0xb5be7573 in xmlOutputBufferCreateFilename__internal_alias () from /usr/lib/libxml2.so.2
#10 0xb5c97912 in xmlSaveFormatFileEnc__internal_alias () from /usr/lib/libxml2.so.2
#11 0xb5c979f8 in xmlSaveFileEnc__internal_alias () from /usr/lib/libxml2.so.2
Seems you are placing the integer value 16 in the XML field, which should be a character string value "16".
Looking at libxml2, it seems you must use the library's functions to change an attriute value.
See libxml2 attribute modification C of how to change an attribute value.

std::remove_if/find_if: Double free or corruption

I have the following std::map defined:
//The map holding the list of registered services per partition key.
std::map<SRServicePartitionKey, std::vector<EndPointAddr*>* > mServiceMap;
I have below indicated function whose aim is to remove a specific EndPointAddr* pointer in the vector that is kept in the value of the above defined Map instance. I am getting a SEGABORT in gdb after the following scenario realized:
Add multiple items to the map
Delete the items using the below function one by one.
Add those deleted items again (a few of them)
Delete one item ==> AT THIS POINT I get a sigabort in GDB with the following message:
* glibc detected * /home/holb/DESIGN/ECLB_CP/REPs/V2/eclb_cp/build_output/ServiceRegistrar: double free or corruption (fasttop): 0x00007ffff0002e10 *
GDB Back trace is available at the bottom...
QUESTION
What particular things do you think are wrong in this removal function below? Why do I get this "Double free or corruption" error? What do you think I am missing in the removal function where I first find the item to be deleted, then remove it from the vector and finally deallocate it.
REMOVAL FUNCTION
bool
ServiceRegistrar::removeService(const EndPointAddr & epAddrForRemoval)
{
bool condErased = false;
for(auto it = mServiceMap.begin(); it != mServiceMap.end(); ++it)
{
std::cout << "\tPartition ["
<< (*it).first.getInstanceNo() << ","
<< (*it).first.getContext() << ","
<< (*it).first.getVersion() << "]:"
<< std::endl;
std::vector<EndPointAddr*> * serviceList = (*it).second;
auto found =
std::find_if(serviceList->begin(),
serviceList->end(),
[epAddrForRemoval]( EndPointAddr* otherEPAddr )
{
const EndPointTipcAddr & tipcAddrToRemove = epAddrForRemoval.getImmutableTipcAddress();
const EndPointTipcAddr & otherTipcAddr = otherEPAddr->getImmutableTipcAddress();
return (tipcAddrToRemove.compareTo(otherTipcAddr));
});
EndPointAddr * toBeDeAllocatedEP = *found;
auto toBeErasedEP =
std::remove_if(serviceList->begin(),
serviceList->end(),
[epAddrForRemoval]( EndPointAddr* otherEPAddr )
{
const EndPointTipcAddr & tipcAddrToRemove = epAddrForRemoval.getImmutableTipcAddress();
const EndPointTipcAddr & otherTipcAddr = otherEPAddr->getImmutableTipcAddress();
return (tipcAddrToRemove.compareTo(otherTipcAddr));
});
if(toBeErasedEP != serviceList->end())
{
serviceList->erase(toBeErasedEP, serviceList->end());
condErased = true;
}
if(toBeDeAllocatedEP != 0)
{
!!!!!!!!!!!!LINE 1396 is HERE!!!!!!!!!!!!!!!
delete toBeDeAllocatedEP;
}
} //end of For Loop
return condErased;
}
GDB BackTrace
(gdb) bt
#0 0x00007ffff7026425 in raise () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007ffff7029b8b in abort () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x00007ffff706439e in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#3 0x00007ffff706eb96 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#4 0x00007ffff7681540 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x0000000000434604 in EndPointIpAddr::~EndPointIpAddr (this=0x7ffff0002fb0, __in_chrg=<optimized out>) at /home/holb/DESIGN/ECLB_CP/REPs/V2/eclb_cp/src/control_components/../control_api/api_util/EndPointIpAddr.hpp:28
#6 0x0000000000434660 in EndPointAddr::~EndPointAddr (this=0x7ffff0002f90, __in_chrg=<optimized out>) at /home/holb/DESIGN/ECLB_CP/REPs/V2/eclb_cp/src/control_components/../control_api/api_util/EndPointAddr.hpp:36
#7 0x000000000043c97f in ServiceRegistrar::removeService (this=0x7fffffffdea0, epAddrForRemoval=...) at /home/holb/DESIGN/ECLB_CP/REPs/V2/eclb_cp/src/control_api/ServiceRegistrar.cpp:1396
You appear to be using found without checking if it's valid or not. If you were to fail to find a value and find_if returned serviceList->end(), you'd be dereferencing serviceList->end().
The variable you're storing this dereferenced value to is the one that's causing you trouble later when you attempt to delete it. Are you sure you're actually finding a matching value?

How to call a v8::Function with custom modified v8::Arguments?

I want to call JSON.stringify method from the C++ side with modified arguments, but any solution that came to my mind results in a weird segfault with all frames being at "??".
I want to do the following:
api::Console is a custom console implementation for debugging purposes and has therefore static methods like api::Console::handleLog or api::Console::handleDebug.
For handleDebug which is passed correctly to the console's ObjectTemplate, the following doesn't work, v8gl::context is the current execution context and is correctly usable in other api implementations:
v8::Handle<v8::Value> Console::handleDebug(const v8::Arguments& args) {
if (args.Length() < 1) {
return v8::Undefined();
}
v8::HandleScope scope;
v8::Handle<v8::Object> global = v8gl::context->Global();
v8::Handle<v8::Object> JSON = global->Get(v8::String::New("JSON"))->ToObject();
v8::Handle<v8::Function> JSON_stringify = v8::Handle<v8::Function>::Cast(JSON->Get(v8::String::New("stringify")));
for (signed a = 0; a < args.Length(); a++) {
for (int m = 0; m < consoleMargin; m++) {
fprintf(stdout, "\t");
}
v8::Handle<v8::Value> passargs[1];
// alternative try was:
// passargs[0] = v8::String::New("{foo:'bar'}");
passargs[0] = v8::String::New(*v8::String::Utf8Value(args[a]->ToString()));
v8::String::Utf8Value value(JSON_stringify->Call(JSON, 1, passargs));
char* message = *value;
fprintf(stdout, "%s\n", message);
}
return scope.Close(v8::Undefined());
}
The backtrace in gdb is somehow weird and I have no idea why:
(gdb) backtrace
#0 0x00000000004a0880 in v8::Context::Global() ()
#1 0x00000000004128ea in api::Console::handleDebug(v8::Arguments const&) ()
#2 0x00000000004b9eab in v8::internal::Builtin_HandleApiCall(v8::internal::(anonymous namespace)::BuiltinArguments<(v8::internal::BuiltinExtraArguments)1>, v8::internal::Isolate*) ()
#3 0x000004cd67f0618e in ?? ()
#4 0x000004cd67f12998 in ?? ()
#5 0x000004cd67f060e1 in ?? ()
# (... etc ...)
So my question is the following:
How do I cast correctly from the Local value"v8::Arguments& args" to "v8::Handle<v8::Value>*" for usage with the Call() method of v8::Function?
If I want to use the args[a] directly in the loop, compiler errors are thrown for the differing signature of v8::Function::Call, which is correct due to args being a Local Value. The signature of v8::Function::Call is the following:
v8::Local<v8::Value> v8::Function::Call(v8::Handle<v8::Object>, int, v8::Handle <v8::Value>*)
// Edit: Updated passargs[false index]
You have error there:
v8::Handle<v8::Value> passargs[1];
passargs[1/* SHOULD BE 0!!!*/] =
v8::String::New(*v8::String::Utf8Value(args[a]->ToString()));
So you try to access element out of array bounds.
BTW: v8::Local<> is inherited from v8::Handle<> so you don't need any magic to convert Local to Handle.
Edit: Most of v8 features require not only v8::HandleScope but also v8::Context::Scope seems you need to create context scope too.
You can get valid context form args:
Local<Object> self = args.Holder();
Persistent<Context> context(self->CreationContext());
Then create handle scope and context scope:
Context::Scope work_in_context_scope(context);
HandleScope work_in_this_function_scope;
Then do you job.