C++ std::unordered_set SIGFPE 异常

标签 c++ stl unordered-set sigfpe

我写了一个程序,我运行了几十次,这让我觉得很有趣——我什至记下了多次执行的结果——但现在它不起作用了。

您可能认为我这么说太狂妄了,或者我可能只是更改了一些台词,但我确实不记得对程序进行过任何更改。 p>

问题是 SIGFPE ,根据输入,在程序的不同执行中出现。尽管在 std::unordered_set<Point<T> *> 中插入一个值时发出信号,但会发生这种情况.

这是我进行此类插入的代码片段:

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) ...

这里的问题是:因为我在我的程序中进行的计算可能会导致被零除——尽管它们与这个过程没有直接关系——,bug 是否有可能被插入遮挡了吗?或者我应该在 std::unordered_set<T> 中插入指针时做一些额外的处理吗? ?

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

最佳答案

我怀疑 'c' 超出了 _cluster 的范围。您能否将所有 _cluster[c] 替换为 _cluster.at(c),并查看它是否发现了超出范围的错误。

valgrind 输出表明它是一个无效读取,后跟一个整数模数错误。由于它正在执行 hash_code % bucket_count,我怀疑您访问的 vector 超出了 vector 的范围。

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

关于C++ std::unordered_set SIGFPE 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14655561/

相关文章:

c++ - 可 move 元素的 vector 会有效地调整大小吗?

c++ - C++ 中的 Runge-Kutta (RK4) 导数

c++ - 在 C++ 中处理 UTF-8

c++ - 标准流适配器

C++:在 main() 之外播种随机数生成器

c++ - 基于模板参数的不同类实现

c++ - 通过使用指令调用开始和结束?

c++ - C++ 中无序关联容器的哈希函数

c++ - 是否可以通过桶迭代器从 std::unordered_set 中删除元素?

c++ - std::为无序集(或映射)插入迭代器?