C ++: использование итератора density_hash_set после стирания (* it) - PullRequest
0 голосов
/ 29 января 2019

У меня есть этот файл кода C ++ , который FOSS по лицензии Expat.При запуске cppcheck в коде я получаю эту ошибку:

[google_hash.cpp:137] -> [google_hash.cpp:141]: (error) Iterator 'it' used after element has been erased.

Код, о котором идет речь:

    74  #if (FCS_WHICH_STATES_GOOGLE_HASH == FCS_WHICH_STATES_GOOGLE_HASH__SPARSE)
    75  typedef sparse_hash_set<char *, state_hash, state_equality> StatesGoogleHash;
    76  #else
    77  typedef dense_hash_set<char *, state_hash, state_equality> StatesGoogleHash;
    78  #endif
.
.
.
   131  extern void fc_solve_states_google_hash_foreach(
   132      fcs_states_google_hash_handle void_hash,
   133      bool (*should_delete_ptr)(void *key, void *context), void *context)
   134  {
   135      StatesGoogleHash *hash = (StatesGoogleHash *)void_hash;
   136
   137      for (StatesGoogleHash::iterator it = hash->begin(); it != hash->end(); ++it)
   138      {
   139          if (should_delete_ptr(*(it), context))
   140          {
   141              hash->erase(it);
   142          }
   143      }
   144  }

Используетсяhttp://goog -sparsehash.sourceforge.net / doc / sparse_hash_set.html или http://goog -sparsehash.sourceforge.net / doc / dens_hash_set.html .

Теперь в этих документах говорится, что

Validity of Iterators

insert() invalidates all iterators, as does resize().
erase() is guaranteed not to invalidate any iterators.

Итак, мой вопрос - правильно ли я использую итераторы наборов правильно и безопасно (а cppcheck выдал ложное срабатывание), или, если нет - как должен кодбыть исправленным?

Помощь будет оценена.

1 Ответ

0 голосов
/ 29 января 2019

Это ложное срабатывание в том смысле, что cppcheck считает, что API с именем erase на iterator делает недействительным итератор.Это правило, которое он использует, потому что это разумный API.

Тогда для этого кода, кажется, допустимо сделать ++it из-за этого:

Это реализованоделая erase () не изменяющим размер хеш-таблицы.Если вам нужна максимальная эффективность использования пространства, вы можете вызвать resize (0) после строки вызовов erase (), чтобы принудительно изменить размер хеш-таблицы до минимально возможного размера.

Похоже, это означает, чтоИтераторы могут встретить удаленные объекты, если вы не вызываете resize(0) между стиранием.Здесь все хорошо, потому что стирание выполняется в одном цикле.

Тот факт, что этот код скрывает свое поведение, не делая его очевидным и не используя стандартные шаблоны, не помогает.

...