2

我有这个 C++ 代码文件 ,它是 Expat 许可证下的FOSS 。在代码上运行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.htmlhttp://goog-sparsehash.sourceforge.net/doc/dense_hash_set.html

现在,这些文件说

Validity of Iterators

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

所以我的问题是 - 我是否正确且安全地使用了集合的迭代器(并且 cppcheck 发出了误报),或者如果没有 - 应该如何修复代码?

帮助将不胜感激。

4

1 回答 1

3

这是一个误报,因为 cppcheck 认为调用 an 的 APIerase会使iterator迭代器无效。这是它使用的规则,因为这是一个明智的 API。

然后对于这段代码,这样做似乎是有效的,++it因为:

这是通过使 erase() 不调整哈希表的大小来实现的。如果您希望获得最大的空间效率,您可以在一串 erase() 调用之后调用 resize(0),以强制哈希表将大小调整为可能的最小大小。

这似乎意味着如果您不在resize(0)擦除之间调用,迭代器可能会遇到已删除的对象。在这里很好,因为擦除是在同一个循环中完成的。

这段代码通过不使其明显并且不使用标准模式来隐藏其行为这一事实无济于事。

于 2019-01-29T15:09:55.493 回答