Creating shared_ptr seems to cause segfault - c++

I have the following function
static node_ptr make_node_ptr()
{
return node_ptr(new node());
}
where using node_ptr = std::shared_ptr<node>;
I tried to find my segmentation fault with valgrind and gdb. In both I get more or less the same stack trace.
Program received signal SIGSEGV, Segmentation fault.
0x00007fff8f5d7e82 in szone_malloc_should_clear () from /usr/lib/system/libsystem_malloc.dylib
(gdb) bt
#0 0x00007fff8f5d7e82 in szone_malloc_should_clear () from /usr/lib/system/libsystem_malloc.dylib
#1 0x00007fff8f5d7877 in malloc_zone_malloc () from /usr/lib/system/libsystem_malloc.dylib
#2 0x00007fff8f5d6395 in malloc () from /usr/lib/system/libsystem_malloc.dylib
#3 0x00000001000f17d8 in operator new(unsigned long) () from /usr/local/lib/gcc/4.9/libstdc++.6.dylib
#4 0x0000000100009c04 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<msc::scene_manager<float, int, 3ul>::node*> (this=0x7fff5f4002e8, __p=0x10059ffc0)
at /usr/local/Cellar/gcc49/4.9.2_1/include/c++/4.9.2/bits/shared_ptr_base.h:569
#5 0x0000000100008c78 in std::__shared_ptr<msc::scene_manager<float, int, 3ul>::node, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<msc::scene_manager<float, int, 3ul>::node> (this=0x7fff5f4002e0, __p=0x10059ffc0)
at /usr/local/Cellar/gcc49/4.9.2_1/include/c++/4.9.2/bits/shared_ptr_base.h:871
#6 0x00000001000079e5 in std::shared_ptr<msc::scene_manager<float, int, 3ul>::node>::shared_ptr<msc::scene_manager<float, int, 3ul>::node> (this=0x7fff5f4002e0, __p=0x10059ffc0)
at /usr/local/Cellar/gcc49/4.9.2_1/include/c++/4.9.2/bits/shared_ptr.h:113
#7 0x0000000100005bdc in msc::scene_manager<float, int, 3ul>::make_node_ptr () at ../../common/msc/scene.d/scene_manager_def.h:98
#8 0x00000001000037dd in msc::scene_manager<float, int, 3ul>::node::generate_wrapping_node (wrappee=...) at ../../common/msc/scene.d/node_impl.h:73
#9 0x0000000100003d53 in msc::scene_manager<float, int, 3ul>::node::generate_wrapping_node (nodes=...) at ../../common/msc/scene.d/node_impl.h:112
#10 0x0000000100004011 in msc::scene_manager<float, int, 3ul>::insert (this=0x7fff5f82ee90, root=..., other=...) at ../../common/msc/scene.d/scene_manager_impl.h:97
#11 0x0000000100006071 in msc::scene_manager<float, int, 3ul>::insert_if_leq (this=0x7fff5f82ee90, root=..., other=...) at ../../common/msc/scene.d/scene_manager_impl.h:127
The last 2 lines repeat endlessly, I guess at least, as I tried to continue until frame #6000 or smth.
Am I missing something or is the creation of this shared_ptr not allowed?
Edit
node_ptr scene_manager::insert(node_ptr & root, node_ptr other)
{
bool swapped = false;
if (root == nullptr)
root = other;
else
{
auto inside = msc::inside::test(*root, *other);
if (inside == msc::inside::NONE)
{
auto oldRoot = root;
root = node::generate_wrapping_node(
std::vector<node_c_ptr>{ oldRoot, other });
insert_if_leq(root, oldRoot);
}
else if ((swapped = (inside == msc::inside::FIRST)))
{
std::swap(root, other);
}
other = insert_if_leq(root, other);
}
return !swapped ? other : root;
}
node_ptr scene_manager::insert_if_leq(node_ptr root, node_ptr other)
{
node_ptr res = root;
if (are_similar(*root, *other))
msc::move_append(root->children, other->children);
else
{
auto idx = root->get_quadrant_idx(other->center);
res = insert(root->quadrants[idx], other);
}
return res;
}
These are the functions which repeat. msc is my own namespace.

As the functions are recursive insert calls insert_if_leq and vice versa, I had to make node_ptr root in insert_if_leq a reference, because the assignment in insert depended on it. The new function definitions are as follows:
node_ptr scene_manager::insert(node_ptr & root, node_ptr other)
node_ptr scene_manager::insert_if_leq(node_ptr & root, node_ptr other)

Related

Getting a 'double free or corruption' error with calls to a function within a recursive function

I have a recursive function solveCountdownProblem which calls evaluateCountdown which takes an expression in reverse-polish notation format. evaluateCountdown is in a series of nested for loops (in solveCountdownProblem) so is called a lot of times.
double evaluateCountdown(string rpnIn) {
vector<double> stack;
double a = 0, b = 0;
string token = "";
char arithToken;
for (int i = 0; i < rpnIn.size(); ++i) {
if (rpnIn[i] == ' ') {
if (token != "") {
stack.push_back(stod(token)); // Push number to stack
token = "";
}
} else {
if (find(arithOperators.begin(), arithOperators.end(), rpnIn[i]) != arithOperators.end()) { //if char is arithmetic operator
// Pop two numbers of stack and perform operation
// Push result back into stack
arithToken = rpnIn[i];
a = stack.back(); stack.pop_back(); // pops and removes elements
b = stack.back(); stack.pop_back();
if (arithToken == '+') {
stack.push_back(b+a);
} else if (arithToken == '-'){
stack.push_back(b-a);
} else if (arithToken == '/') {
stack.push_back(b/a);
} else if (arithToken == '*') {
stack.push_back(b*a);
}
} else {
token += rpnIn[i]; //add chars to string
}
}
}
return stack.back();
}
It works after some time producing the right calculations but eventually I end up with a memory error 'double free or corruption (out)'. I've used gdb to debug and it produces this backtrace.
Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) backtrace
#0 __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x00007ffff7bee859 in __GI_abort () at abort.c:79
#2 0x00007ffff7c593ee in __libc_message (action=action#entry=do_abort, fmt=fmt#entry=0x7ffff7d83285 "%s\n") at ../sysdeps/posix/libc_fatal.c:155
#3 0x00007ffff7c6147c in malloc_printerr (str=str#entry=0x7ffff7d85670 "double free or corruption (out)") at malloc.c:5347
#4 0x00007ffff7c63120 in _int_free (av=0x7ffff7db4b80 <main_arena>, p=0x5555555733d0, have_lock=<optimized out>) at malloc.c:4314
#5 0x000055555555a932 in __gnu_cxx::new_allocator<double>::deallocate (this=0x7fffffffd270, __p=0x5555555733e0) at /usr/include/c++/9/ext/new_allocator.h:128
#6 0x0000555555559dc0 in std::allocator_traits<std::allocator<double> >::deallocate (__a=..., __p=0x5555555733e0, __n=4) at /usr/include/c++/9/bits/alloc_traits.h:470
#7 0x000055555555932e in std::_Vector_base<double, std::allocator<double> >::_M_deallocate (this=0x7fffffffd270, __p=0x5555555733e0, __n=4) at /usr/include/c++/9/bits/stl_vector.h:351
#8 0x00005555555588fe in std::_Vector_base<double, std::allocator<double> >::~_Vector_base (this=0x7fffffffd270, __in_chrg=<optimized out>) at /usr/include/c++/9/bits/stl_vector.h:332
#9 0x0000555555558953 in std::vector<double, std::allocator<double> >::~vector (this=0x7fffffffd270, __in_chrg=<optimized out>) at /usr/include/c++/9/bits/stl_vector.h:680
#10 0x0000555555556a9a in evaluateCountdown (rpnIn="4 6 5 * + +") at Countdown.h:58
#11 0x0000555555557762 in solveCountdownProblem (operands=std::vector of length 3, capacity 4 = {...}, targetValue=21) at Countdown.h:172
#12 0x0000555555556d61 in solveCountdownProblem (operands=std::vector of length 4, capacity 5 = {...}, targetValue=21) at Countdown.h:113
#13 0x0000555555556d61 in solveCountdownProblem (operands=std::vector of length 5, capacity 6 = {...}, targetValue=21) at Countdown.h:113
#14 0x0000555555556d61 in solveCountdownProblem (operands=std::vector of length 6, capacity 6 = {...}, targetValue=21) at Countdown.h:113
#15 0x0000555555557e17 in main () at TestCountdown.cpp:19
It seems to be pointing to the line 'vector stack;' but I'm not sure why I'm getting a memory error. Doesn't the destructor automatically deallocate 'stack' once it falls out of scope?
If you look into evaluated string "4 6 5 * + +" you can see that there are not enough operands for the last operation + and in your code you do not check if stack has enough elements before calling stack.pop_back() twice. You need to add that check and act accordingly. Probably cleanest way is to wrap popping in a function:
double pop( std::vector<double> &stack )
{
if( stack.empty() ) { // throw exception, return NaN or whatever logic of your program requires
...
}
auto r = stack.back();
stack.pop_back();
return r;
}
then your code is shorter and cleaner:
// Pop two numbers of stack and perform operation
// Push result back into stack
arithToken = rpnIn[i];
double a = pop( stack ); // pops and removes elements
double b = pop( stack );
(and it is better idea to declare and initialize variables when you need them, not in advance)

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.

eraseFromParent() Error

I'm trying to delete some instructions in IR. For analysis purpose, these instructions are inserted before, and now I need to delete them.
BasicBlock::reverse_iterator I = (*b).rbegin();
BasicBlock::reverse_iterator Ie = (*b).rend();
int i=0;
for ( ; I != Ie;I++)
{
if(i>0&&i<4){
errs()<<" Instruction "<<*I<<"\n";
I->eraseFromParent();
i++;
}
else{
i++;
}
}
This code is used in Transformation pass. When I run it, the output error are:
#0 0x00000000032bff15 (opt+0x32bff15)
#1 0x00000000032bffa6 (opt+0x32bffa6)
#2 0x00000000032be43e (opt+0x32be43e)
#3 0x00000000032bf8ac (opt+0x32bf8ac)
#4 0x00007f26cfa81330 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x10330)
#5 0x00007f26ce81a89a llvm::PointerIntPair<llvm::ilist_node_base<true>*, 1u, unsigned int, llvm::PointerLikeTypeTraits<llvm::ilist_node_base<true>*>, llvm::PointerIntPairInfo<llvm::ilist_node_base<true>*, 1u, llvm::PointerLikeTypeTraits<llvm::ilist_node_base<true>*> > >::getInt() const /home/rasha/llvm/llvm/include/llvm/ADT/PointerIntPair.h:59:0
#6 0x00007f26ce813516 llvm::ilist_node_base<true>::isSentinel() const /home/rasha/llvm/llvm/include/llvm/ADT/ilist_node_base.h:46:0
#7 0x00007f26ce813536 llvm::ilist_node_base<true>::isKnownSentinel() const /home/rasha/llvm/llvm/include/llvm/ADT/ilist_node_base.h:47:0
#8 0x00007f 26ce81e1d9 llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, true, false, void>, true, false>::operator*() const /home/rasha/llvm/llvm/include/llvm/ADT/ilist_iterator.h:139:0
#9 0x00007f26ce812d6f (anonymous namespace)::BBRemove::runOnModule(llvm::Module&) /home/rasha/llvm/llvm/lib/Transforms/BBRemove/BBRemove.cpp:79:0
#10 0x0000000002c4a2dc (opt+0x2c4a2dc)
#11 0x0000000002c4aa2c (opt+0x2c4aa2c)
#12 0x0000000002c4ac6d (opt+0x2c4ac6d)
#13 0x0000000001512cd4 (opt+0x1512cd4)
#14 0x00007f26cea6cf45 __libc_start_main /build/eglibc-ripdx6/eglibc-2.19/csu/libc-start.c:321:0
#15 0x00000000014f7a19 (opt+0x14f7a19)
Stack dump:
This error is issued after the first call of eraseFromParent.
BasicBlock::reverse_iterator I = (*b).rbegin();
BasicBlock::reverse_iterator Ie = (*b).rend();
stack<Instruction *> workList;
int i=0;
for ( ; I != Ie;I++)
{
if(i>0&&i<4){
workList.push_back(I);
i++;
}
else{
i++;
}
}
while(!workList.empty()){
Instruction *I=workList.pop();
I->eraseFromParent();
}
Do not modify instruction within the iterator; collect it first then modify.

Vector push back error

I'm using C++ to implement FP-growth algorithm, but I get some errors when using vector. Here is my code:
typedef struct Node
{
FPData *fpData;
int childCount;
struct Node *parent;
vector<Node*> childs;
}FPNode;
FPNode* FPTree::NewNode(string data, int support)
{
FPNode *node = (FPNode*) malloc(sizeof(FPNode));
FPData *fpData = (FPData*) malloc(sizeof(FPData));
fpData -> data = data;
fpData -> support = support;
node -> fpData = fpData;
node -> childCount = 0;
node -> parent = NULL;
return node;
}
void FPTree::InsertFPPath(FPNode* root, list<FPData*> fpDatas)
{
if(fpDatas.size() <= 0)
{
return;
}
bool flag = true;
for(int i = 0; i < root -> childCount; i++)
{
FPNode* child = root -> childs[i];
if(child -> fpData -> data == fpDatas.front() -> data)
{
flag = false;
child -> fpData -> support ++;
fpDatas.pop_front();
InsertFPPath(child, fpDatas);
break;
}
}
if(flag)
{
FPData* firstData = fpDatas.front();
FPNode* newChild = NewNode(firstData -> data, firstData -> support);
root -> childs.push_back(newChild); // error at here
root -> childCount ++;
fpDatas.pop_front();
for(int i = 0; i < fpDatas.size(); i++)
{
InsertFPPath(newChild, fpDatas);
}
}
}
The InsertFPPath() is a recursive method, I get error when second iterate:
root -> childs.push_back(newChild)
The error comes at:
construct(_Up* __p, _Args&&... __args) // here the __p is null, and __args is right
{
::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
}
And the thread Queue stop at:
#0 0x00000001000050cf in void std::__1::allocator::construct(Node**, Node* const&&&) [inlined] at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1673
the backtrace is :
#0 0x00000001000050cf in void std::__1::allocator::construct(Node**, Node* const&&&) [inlined] at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1673
#1 0x00000001000050bc in void std::__1::allocator_traits >::__construct(std::__1::integral_constant, std::__1::allocator&, Node**, Node* const&&&) [inlined] at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1600
#2 0x000000010000509c in void std::__1::allocator_traits >::construct(std::__1::allocator&, Node**, Node* const&&&) [inlined] at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1453
#3 0x0000000100005079 in std::__1::vector >::push_back(Node* const&) [inlined] at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:1590
#4 0x0000000100004fa9 in FPTree::InsertFPPath(Node*, std::__1::list >) at /Users/dorothy/ME/USTC/作业/数据挖掘/experiment/FPTree/FPTree/FPTree.cpp:129
#5 0x00000001000051b4 in FPTree::InsertFPPath(Node*, std::__1::list >) at /Users/dorothy/ME/USTC/作业/数据挖掘/experiment/FPTree/FPTree/FPTree.cpp:135**
When you allocate memory for structures (struct or class) containing constructors, or for structures containing objects that have constructors, then you can't allocate the memory using malloc. The malloc function only allocates memory, but it doesn't call the constructors, and in your case that means that the childs member object will not be constructed and using the vector will lead to undefined behavior.
When allocating memory dynamically in C++ you need to use the new operator:
FPNode *node = new FPNode;
FPData *fpData = new FPData;

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.