Вставка (строка, объект *) в хеш-таблицу (C ++) - PullRequest
1 голос
/ 30 октября 2009

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

У меня сейчас (спасибо предыдущим авторам):

// 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 у меня есть:

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

Кажется, это работает нормально. Я получаю ошибку сегмента при попытке следующей вставки:

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 , похоже, все должно быть в порядке. В чем дело? Я думаю о переходе на контейнер карт, чтобы сэкономить время отладки ...

Обновление

Что-то в инициализации кажется неправильным. Когда я доберусь до

strainTable[ mutantSeq ] = *mItr;

отладчик сообщает «EXC_BAD_ACCESS» и переходит на

_Node* __first = _M_buckets[__n];

из hashtable.h.

Ответы [ 3 ]

1 голос
/ 31 октября 2009

В качестве диагностического подхода на самом деле в строке выполняются 2 инструкции:

  1. Поиск в strainTable, который возвращает ссылку
  2. Разыменование итератора
  3. Присвоение значения для ссылки

Здесь вы можете выбрать Divide and Conquer подход:

  strainTable[ mutantSeq ] = *mItr; // <-- Seg fault happens here

Становится

  Strain*& aReference = strainTable[ mutantSeq ];
  Strain* const aPtr = *mItr;
  aReference = aPtr;

(это общий совет)

На какой линии происходит ошибка сегмента? Возможно ли иметь 10 первых кадров в стеке?

При поиске в Google я обнаружил отчет об ошибке , который предполагает, что могут быть проблемы с hash_map ...

Возможно, лучше по возможности использовать unordered_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;
0 голосов
/ 31 октября 2009

Смущающее «решение» заключается в том, что я обнаружил, что не объявил полный размер двумерного массива в заголовочном файле класса. Когда я инициализировал массив в конструкторе, он перезаписал часть пространства для хеш-таблицы.

Благодаря предложенным здесь предложениям я перешел на std :: tr1 :: unordered_map!

0 голосов
/ 30 октября 2009

Я не вижу ничего плохого с этим кодом. Ошибка должна быть в другом месте. Может быть, значение (* mItr) -> getSequence (), которое дает недопустимую строку, или что-то в этом роде.

В качестве оптимизации оператор () может принимать строку const & вместо строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...