Question

I've been pulling out my hair to figure out this segfault and decided to ask some help.
I have a boost::multi_index container, which contains (string, string, double) and it hits a segfault at some point.

Here's a simplified version of my code:

#include<iostream>
....

// mySet is a multi_index container which contains <(string str1), (string str2), (double val)>

typedef mySet::index<str1>::type set_by_str1;

...

for(unsigned int i=0; i < token.size(); ++i)
{
    set_by_str1::iteration it = myContainer.get<str1>().find(token[i]);
    while(it->str1() == token[i])
    {
        cout << it->str1() << ", " << it->str2() << ", " << it->val << endl;
    }
    *it++;
}

This code seems working pretty well, but it crashes only when it hits some specific token.(Oppositely speaking, it never crashes when this doesn't meet the token).
I guess this happens because it goes above the range of container itself but don't understand how it possibly could happen.

GDB error message displays:

Program received signal SIGSEGV, Segmentation fault.
0x08052e83 in std::string::size (this=0x806e190) at /usr/include/c++/4.4/bits/basic_string.h:629
629       { return _M_rep()->_M_length; }

(gdb) bactrace full
#0  0x08052e83 in std::string::size (this=0x806e190) at /usr/include/c++/4.4/bits/basic_string.h:629
No locals.
#1  0x08050475 in std::operator<< <char, std::char_traits<char>, std::allocator<char> > (__os=..., __str=...)
    at /usr/include/c++/4.4/bits/basic_string.h:2503
No locals.
#2  0x0804e4e0 in MyClass:MyFunction (this=0xbffff534) at src/MyCode.cpp:353 (This is where while condition exists)
... dump of HUGE trace for multi_index ...

and it obviously crashes when I call it->str1() in while condition, not because of the token vector. How can I prevent this? I tried to add if(it == myContainer.get<str1>().end()) break; right below *it++, but didn't help.
Would anyone give me some clue?
Thank you!

Was it helpful?

Solution

There are a number of problems with your code:

  • It will crash if there's no element in the container equivalent to token[i], since then find returns end(), which is not dereferenceable.
  • During the while loop it can reach the end of the container, and again you won't be able to deference it.
  • find won't get you the first element with key equivalent to token[i], which is presumably what you want; use lower_bound instead.

I suggest you change the code as follows:

pair<set_by_str1::iterator, set_by_str1::iterator> p =
    myContainer.get<str1>().equal_range(token[i]);

while(p.first!=p.second)
{
    cout << p.first->str1() << ", " << p.first->str2() << ", "
         << p.first->val << endl;
    ++(p.first);
}

OTHER TIPS

Either it->str1() is null or token[i] is null.

Ensure that they aren't null and the segmentation fault will go away.

You may want to replace the while with an if, also be aware that if find is algorithms find from here, if the item is not found it returns the iterator as the iterator of the last element, which may have str1 as null.

Also are you sure you want to iterator over the token string character by character and print each match per token character rather than just printing one match for the entire token string ?(at least I think it is a string, as your sample code doesn't define it).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top