Вопрос

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

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

#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++, но не помогло.
Кто-нибудь даст мне какую-нибудь подсказку?
Спасибо!

Это было полезно?

Решение

В вашем коде есть ряд проблем:

  • Он выйдет из строя, если в контейнере нет элемента, эквивалентного 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);
}

Другие советы

Или it->str1() является нулевым или token[i] нулевой.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top