【问题标题】:C++ std::unordered_set SIGFPE exceptionC++ std::unordered_set SIGFPE 异常
【发布时间】:2013-02-01 21:45:44
【问题描述】:

我写了一个程序,我很高兴我会运行它几十次——我什至写下了多次执行的结果——现在它不起作用了。

你可能会认为我这么说很过分,或者我可能只是改变了一些台词,但我真的不记得对程序做过任何修改。 p>

问题是SIGFPE,根据输入,它在程序的不同执行中出现。在std::unordered_set<Point<T> *>中插入值时发出信号时发生。

这是我进行此类插入的代码的 sn-p:

std::vector<Point<T> *> _point, _centroid;
std::vector<std::unordered_set<Point<T> *> > _cluster;

// Main procedure -- pseudocode
for (point in _point) {
    cluster_id = centroid_with_min_distance(point, _centroid);
    has_changed = _change_cluster(point, cluster_id);
}

// Changes from one "point->_cluster's unordered_set" to "c's unordered_set"
bool _change_cluster(Point<T> *point, const unsigned int& c) {

    if ((point->_cluster == c) &&
        (_cluster[c].find(point) != _cluster[c].end())) {
        return false;
    }

    _cluster[point->_cluster].erase(point);
    _cluster[c].insert(point); // Insertion that raises the SIGFPE exception
    point->_cluster = c;
    return true;

}

这是 valgrind 输出的一个被认为很重要的部分:

==17636== Invalid read of size 8
==17636==    at 0x40A758: std::pair<std::__detail::_Hashtable_iterator<
                Point<unsigned int>*, true, false>, bool>
                std::_Hashtable<Point<unsigned int>*, Point<unsigned int>*,
                std::allocator<Point<unsigned int>*>,
                std::_Identity<Point<unsigned int>*>,
                std::equal_to<Point<unsigned int>*>,
                std::hash<Point<unsigned int>*>,
                std::__detail::_Mod_range_hashing,
                std::__detail::_Default_ranged_hash,
                std::__detail::_Prime_rehash_policy, false, true, true>::
                    _M_insert<Point<unsigned int>* const&>(
                        Point<unsigned int>* const&&&,
                        std::integral_constant<bool, true>) (hashtable.h:966)
==17636==    by 0x408EDA: std::_Hashtable<Point<unsigned int>*,
                 Point<unsigned int>*, std::allocator<Point<unsigned int>*>,
                 std::_Identity<Point<unsigned int>*>,
                 std::equal_to<Point<unsigned int>*>,
                 std::hash<Point<unsigned int>*>,
                 std::__detail::_Mod_range_hashing,
                 std::__detail::_Default_ranged_hash,
                 std::__detail::_Prime_rehash_policy, false, true, true>::
                     insert(Point<unsigned int>* const&) (hashtable.h:400)
==17636==  ... (calls from my program) ...
==17636==  Address 0x620a028 is not stack'd, malloc'd or (recently) free'd
==17636== 
==17636== 
==17636== Process terminating with default action of signal 8 (SIGFPE)
==17636==  Integer divide by zero at address 0x402D07D7C
==17636==    at 0x40252F: std::__detail::_Mod_range_hashing::operator()(
                 unsigned long, unsigned long) const (hashtable_policy.h:376)
==17636==    by 0x40A66C: std::__detail::_Hash_code_base<Point<unsigned int>*,
                 Point<unsigned int>*, std::_Identity<Point<unsigned int>*>,
                 std::equal_to<Point<unsigned int>*>,
                 std::hash<Point<unsigned int>*>,
                 std::__detail::_Mod_range_hashing,
                 std::__detail::_Default_ranged_hash, false>::_M_bucket_index(
                     Point<unsigned int>* const&, unsigned long,
                     unsigned long) const (hashtable_policy.h:758)
==17636==    by 0x40A772: std::pair<std::__detail::_Hashtable_iterator<
                 Point<unsigned int>*, true, false>, bool>
                 std::_Hashtable<Point<unsigned int>*, Point<unsigned int>*,
                 std::allocator<Point<unsigned int>*>,
                 std::_Identity<Point<unsigned int>*>,
                 std::equal_to<Point<unsigned int>*>,
                 std::hash<Point<unsigned int>*>,
                 std::__detail::_Mod_range_hashing,
                 std::__detail::_Default_ranged_hash,
                 std::__detail::_Prime_rehash_policy, false, true, true>::
                     _M_insert<Point<unsigned int>* const&>(
                     Point<unsigned int>* const&&&,
                     std::integral_constant<bool, true>) (hashtable.h:966)
==17636==    by 0x408EDA: std::_Hashtable<Point<unsigned int>*,
                 Point<unsigned int>*, std::allocator<Point<unsigned int>*>,
                 std::_Identity<Point<unsigned int>*>,
                 std::equal_to<Point<unsigned int>*>,
                 std::hash<Point<unsigned int>*>,
                 std::__detail::_Mod_range_hashing,
                 std::__detail::_Default_ranged_hash,
                 std::__detail::_Prime_rehash_policy, false, true, true>::
                     insert(Point<unsigned int>* const&) (hashtable.h:400)
==17636==    ... (calls from my program) ...

这里的问题是:由于我的程序中有可能导致除以零的计算——尽管它们与此过程没有直接关系——是否有可能是 错误被插入遮蔽了吗?或者在std::unordered_set&lt;T&gt; 中插入指针时我应该做一些额外的处理吗?

我在x86_64 GNU/Linux下编译程序,我用的是g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

【问题讨论】:

  • 你能在失败的函数周围发布一段代码吗?您还在片场执行哪些其他操作?此外,您似乎使用std::hash&lt;Point&lt;T&gt;*&gt;std::equal_to&lt;Point&lt;T&gt;*&gt; 作为您的散列和等于函数,这意味着它是基于对象地址的散列,而不是点本身的数据。
  • @DaveS 感谢您的回复。是的,我确实将指针存储在std::unordered_set&lt;&gt; 中,这就是我想要做的,因为我只需要通过恒定时间搜索来跟踪对象。我将在这里添加涉及的sn-p。
  • @Rubens:如果你的程序有未定义的行为,它可能会运行好几个世纪,然后在第 100 亿次执行时崩溃。当您使用指针时,很容易获得 UB。另一个原因可能是,您一直在更改 unordered_set&lt;&gt; 中的值。如果希望我们提供帮助,我相信您需要向我们展示代码。
  • @AndyProwl 谢谢,我已尝试缩小代码范围以直截了当。请检查更新!
  • @Rubens: 你如何检查c 是否小于_cluster 的大小?我在这里看到了潜在的越界。

标签: c++ stl unordered-set sigfpe


【解决方案1】:

我怀疑“c”超出了_cluster 的范围。能不能把所有的_cluster[c]都换成_cluster.at(c),看看有没有发现超出范围的错误。

valgrind 输出表明它是无效读取,后跟整数模数错误。由于它在做hash_code % bucket_count,我怀疑你访问的范围超出了向量的范围。

顺便说一句,以_ 开头的东西命名可能是有风险的,就好像它在全局命名空间中一样,它在技术上是为实现而保留的。

【讨论】:

  • 谢谢。我喜欢用首字母_ 命名private members,因为我通常不使用this-&gt;——这些实例在一个更大的类中,并且它们是私有的。我现在正在尝试这个解决方案!
  • 是的,这正是问题所在。哎呀,我很惭愧我没有得到这个 - 我想我被SIGFPE误导了(:谢谢大家的支持!
猜你喜欢
  • 1970-01-01
  • 2017-11-27
  • 1970-01-01
  • 2011-10-08
  • 2020-07-26
  • 2012-11-21
  • 1970-01-01
  • 1970-01-01
  • 2015-10-01
相关资源
最近更新 更多