SIGSEGV ao explorar boost::multi_index
-
11-12-2019 - |
Pergunta
Eu fui puxando meu cabelo para descobrir esse segfault e decidiu pedir ajuda.
Eu tenho um boost::multi_index
recipiente que contém (string, string, double)
e ele acerta um segfault em algum ponto.
Aqui está uma versão simplificada do meu código:
#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++;
}
Este código parece funcionar muito bem, mas falha somente quando ele atinge alguns específico do token.(Ao contrário de falar, nunca falha quando este não atender o token).
Eu acho que isso acontece porque it
vai acima do intervalo de recipiente próprio, mas não entende como é que isso poderia acontecer.
GDB mensagem de erro é exibida:
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 ...
e isso, obviamente, falha quando eu chamo it->str1()
enquanto condição, não porque o token de vetor.Como posso evitar isso?Eu tentei adicionar if(it == myContainer.get<str1>().end()) break;
logo abaixo *it++
, mas não ajuda.
Que alguém poderia me dar alguma pista?
Obrigado!
Solução
Há uma série de problemas com o seu código:
- Ele irá falhar se não existir nenhum elemento do contêiner equivalente a
token[i]
, desde entãofind
retornaend()
, que não é dereferenceable. - Durante o
while
loopit
pode chegar o final do recipiente, e, novamente, você não será capaz de deferência-lo. find
não obter o primeiro elemento com chave equivalente atoken[i]
, que é provavelmente o que você quer;utilizaçãolower_bound
em vez disso.
Eu sugiro que você altere o código da seguinte maneira:
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);
}
Outras dicas
Ou it->str1()
é nulo ou token[i]
é nulo.
Certifique-se de que eles não são nulos e a falha de segmentação, vai embora.
Você pode querer substituir o while
com um if
, também estar ciente de que se encontra é encontrar a partir de algoritmos aqui, se o item não for encontrado, retorna o iterador como o iterador de o último elemento, o que pode ter str1
como null.
Também tem certeza de que deseja iterador sobre o token de cadeia de caractere por caractere e impressão de cada jogo por token de caracteres ao invés de incluir somente a impressão de um jogo para toda a cadeia de token ?(pelo menos eu acho que é uma seqüência de caracteres, como o código de exemplo não a definem).