SIGSEGV во время изучения наддува :: multi_index - PullRequest
0 голосов
/ 11 марта 2012

Я выдернул свои волосы, чтобы выяснить это, и решил попросить помощи.
У меня есть контейнер boost::multi_index, который содержит (string, string, double), и в какой-то момент он попадает в segfault.

Вот упрощенная версия моего кода:

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

Этот код работает довольно хорошо, но он падает только при попадании в определенный токен (напротив, он никогда не падает, если не соответствует токену).
Я думаю, это происходит потому, что it выходит за пределы диапазона самого контейнера, но не понимаю, как это могло произойти.

Появляется сообщение об ошибке GDB:

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 ...

и он явно падает, когда я вызываю it->str1() в состоянии while, а не из-за вектора токена. Как я могу предотвратить это? Я пытался добавить if(it == myContainer.get<str1>().end()) break; прямо под *it++, но не помогло.
Кто-нибудь подскажет?
Спасибо!

Ответы [ 2 ]

0 голосов
/ 11 марта 2012

Существует ряд проблем с вашим кодом:

  • Сбой, если в контейнере нет элемента, эквивалентного token[i], с тех пор find возвращает end(), что не является разыменованием.
  • Во время цикла while it может достигнуть конца контейнера, и вы снова не сможете его задержать.
  • find не даст вам первый элемент с ключом, эквивалентным token[i], что, вероятно, то, что вы хотите; используйте вместо этого lower_bound.

Я предлагаю вам изменить код следующим образом:

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);
}
0 голосов
/ 11 марта 2012

Либо it->str1() равно нулю, либо token[i] равно нулю.

Убедитесь, что они не равны нулю, и ошибка сегментации исчезнет.

Возможно, вы захотите заменить while на if, также имейте в виду, что если find - это алгоритмы поиска из здесь , если элемент не найден, он возвращает итератор как итератор последний элемент, который может иметь str1 как ноль.

Также вы уверены, что хотите перебрать символьную строку токена и печатать каждое совпадение на символьный символ, а не просто печатать одно совпадение для всей строки токена? (По крайней мере, я думаю, что это строка, как пример код не определяет это).

...