I wrote a program and I'm quite amused by the fact that I'd run it dozens of times -- I've even wrote down results from multiple executions --, and now it does not work.
You might think I'm high as a kite to say so, or that I might have simply changed some lines, but I really do not recall doing any alterations whatsoever on the program.
The problem is a SIGFPE, that raises up in different executions of the program, according to the input. Happens though the signal is raised while inserting a value in an std::unordered_set<Point<T> *>.
Here is a snippet of the code where I do such insertion:
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;
}
Here is a considered-important section of valgrind's output:
==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) ...
The question here is: as I have calculations in my program that may result in divisions by zero -- they are not directly related to this process, though --, is it possible that the bug is being shadowed by the insertion? Or should I do some extra treatment while inserting pointers in an std::unordered_set<T>?
I'm compiling the program under x86_64 GNU/Linux, and I'm using g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3.
I suspect that 'c' is out of the range of _cluster. Can you replace all of the _cluster[c] with _cluster.at(c), and see if it finds an out of range error.
The valgrind output indicates that it's an invalid read followed by an integer modulus error. Since it's doing hash_code % bucket_count, I suspect that you accessed out of the range of the vector.
As an aside, naming things that start with _ can be risky, as if it's in the global namespace, it is technically reserved for the implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With