Inserindo (cadeia, objeto *) na tabela de hash (C ++)
Pergunta
Esta questão é uma offgrowth da minha pergunta anterior na criação de um hash mesa para chaves de cadeia de loja e os ponteiros como dados. Eu estou recebendo uma falha seg pós-construção quando eu tento adicionar entradas para a minha mesa hash. Eu ainda estou muito confuso sobre o que a sintaxe é apropriado.
Eu tenho atualmente (graças a cartazes anteriores):
// Simulation.h
#include <ext/hash_map>
using namespace __gnu_cxx;
...
typedef struct { size_t operator()( const string& str ) const
{ return __gnu_cxx::__stl_hash_string( str.c_str() ); } } strhash;
struct eqstr {
bool operator()(string s1, string s2) const {
return ( s1.compare(s2) == 0 );
}
};
....
hash_map< string, Strain *, strhash, eqstr > strainTable;
Na minha construtor Simulation, eu tenho:
// Simulation.cpp
Simulation::Simulation() : ... {
string MRCA;
for ( int b = 0; b < SEQ_LENGTH; b++ ) {
int randBase = rgen.uniform(0,NUM_BASES);
MRCA.push_back( BASES[ randBase ] );
}
Strain * firstStrainPtr;
firstStrainPtr = new Strain( idCtr, MRCA, NUM_STEPS );
strainTable[ MRCA ]= firstStrainPtr; // <-- Hash table initialization
....
}
Este parece funcionar bem. Eu recebo uma falha seg quando a seguinte inserção é tentada:
void Simulation::updateSimulation( double t ) {
....
// Add mutants to liveStrains() and strainTable
vector< Strain * >::const_iterator mItr = newMutants.begin();
for ( mItr = newMutants.begin(); mItr != newMutants.end(); ++mItr ) // for each mutant in deme
{
string mutantSeq = ( *mItr )->getSequence();
cout << "mutantSeq is " << mutantSeq << endl; // <-- This is fine
liveStrains.push_back( *mItr );
strainTable[ mutantSeq ] = *mItr; // <-- Seg fault happens here
}
newMutants.clear();
....
}
A leitura da terceira nota do operador [] no SGI documentação , isso parece que deve ser fino. O que há de errado? Estou pensando em mudar para um recipiente do mapa apenas para poupar tempo de depuração ...
Atualizar
Algo sobre a inicialização parece errado. Quando eu chegar
strainTable[ mutantSeq ] = *mItr;
os relatórios de depurador "EXC_BAD_ACCESS" e salta para
_Node* __first = _M_buckets[__n];
de hashtable.h.
Solução
Como uma abordagem diagnóstico, você realmente tem 2 instruções executadas na linha:
- Lookup em
strainTable
, que retorna uma referência - Dereferencing o iterador
- atribuição de um valor de referência
Aqui você pode querer ter uma abordagem Divide and Conquer
:
strainTable[ mutantSeq ] = *mItr; // <-- Seg fault happens here
Torna-se
Strain*& aReference = strainTable[ mutantSeq ];
Strain* const aPtr = *mItr;
aReference = aPtr;
(que é um conselho geral)
Em qual linha ocorre a falha seg? Seria possível ter os 10 primeiros quadros de pilha?
Enquanto olhando para cima Google, eu vim este relatório de bug , o que sugere que pode haver problemas com o hash_map
...
Você pode ser melhor fora de usar a unordered_map , se possível, como é claramente indicado que o tempo não será levado a fixação do hsah_map
visto como um recipiente legado (e este era 2005 ...). Note-se que ele deve estar disponível se você usar o GCC 4.x (não tenho certeza para 3.x)
A principal vantagem é que a estrutura hash
e comparison predicate
já trabalho para std::string
para que você não tem sequer a implementá-los a si mesmo:)
Tudo que você tem que fazer, por isso, se você tem isso em seu compilador, é escrever o seguinte:
#include <tr1/unordered_map>
typedef std::tr1::unordered_map<std::string, Strain*> strain_hash_map;
Outras dicas
Eu não posso ver qualquer mal com este código. O erro tem que ter em outro lugar. Talvez o valor de (* Mitr) -.> GetSequence (), que está dando uma cadeia inválida, ou algo parecido
Como uma otimização, o operador () poderia levar const corda e em vez de apenas o fio de.
A "solução" embaraçoso é que eu descobri que eu não tinha declarado o tamanho natural de uma matriz bidimensional no arquivo de cabeçalho de classe. Quando eu inicializado a matriz no construtor, isso aconteceu para substituir algum do espaço para a tabela de hash.
Graças às sugestões aqui, eu agora mudou-se para um std :: tr1 :: unordered_map!