Вставка (string, object * ) в хэш-таблицу (C ++)
Вопрос
Этот вопрос является результатом моего предыдущий вопрос о создании хэш-таблицы для хранения строковых ключей и указателей в качестве данных.Я получаю ошибку seg после конструирования, когда пытаюсь добавить записи в свою хэш-таблицу.Я все еще очень смущен тем, какой синтаксис является подходящим.
В настоящее время у меня есть (благодаря предыдущим постерам):
// 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;
В моем конструкторе моделирования у меня есть:
// 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
....
}
Кажется, это работает нормально.Я получаю ошибку seg при попытке следующей вставки:
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();
....
}
Читая третье примечание об операторе[] в Документация SGI, кажется, что все должно быть в порядке.Что случилось?Я подумываю о переходе на контейнер map просто для экономии времени отладки...
Обновить
Что-то в инициализации кажется неправильным.Когда я доберусь до
strainTable[ mutantSeq ] = *mItr;
отладчик сообщает "EXC_BAD_ACCESS" и переходит к
_Node* __first = _M_buckets[__n];
из хэш-таблицы.h.
Решение
Как подход к диагностике, у вас на самом деле есть 2 инструкции, выполняемые в строке:
- Поиск в
strainTable
, который возвращает ссылку - Разыменование итератора
- Присвоение значения ссылке
Здесь вы, возможно, захотите воспользоваться Divide and Conquer
подход:
strainTable[ mutantSeq ] = *mItr; // <-- Seg fault happens here
Становится
Strain*& aReference = strainTable[ mutantSeq ];
Strain* const aPtr = *mItr;
aReference = aPtr;
(это общий совет)
На какой линии возникает ошибка seg ?Возможно ли было бы иметь 10 первых кадров стека ?
Просматривая Google, я наткнулся на следующее отчет об ошибке, что наводит на мысль о возможных проблемах с hash_map
...
Возможно, вам было бы лучше использовать неупорядоченная карта если это возможно, поскольку четко указано, что устранение неполадок не займет много времени. hsah_map
рассматривался как устаревший контейнер (а это был 2005 год ...).Обратите внимание, что он должен быть доступен, если вы используете GCC 4.x (не уверен для 3.x)
Главное преимущество заключается в том, что hash
структура и comparison predicate
уже работаете на std::string
так что вам даже не придется реализовывать их самостоятельно :)
Поэтому все, что вам нужно сделать, если у вас есть это в вашем компиляторе, это написать это:
#include <tr1/unordered_map>
typedef std::tr1::unordered_map<std::string, Strain*> strain_hash_map;
Другие советы
Я не вижу ничего плохого в этом коде.Ошибка должна быть в другом месте.Возможно, значение (* mItr)-> getSequence(), которое выдает недопустимую строку, или что-то в этом роде.
В качестве оптимизации operator() мог бы принимать string const& вместо просто string .
Смущающее "решение" заключается в том, что я обнаружил, что не объявил полный размер двумерного массива в файле заголовка класса.Когда я инициализировал массив в конструкторе, случилось так, что часть пространства для хэш-таблицы была перезаписана.
Благодаря приведенным здесь предложениям, теперь я перешел к std::tr1::unordered_map!