Использование gcc 4.8.1 и libboost 1.53 Я получаю разные результаты в зависимости от уровней оптимизации, которые я использую для компиляции мой код. В рамках большой программы функция insertValues
выполняется дважды для одной и той же a
, key
и value
:boost :: unordered_map :: find производит разные результаты в зависимости от уровня оптимизации компилятора, а boost :: unordered_map :: insert производит то же самое
/* Complex classes */
class A { /*....*/ }
class Value { /*.....*/ }
class SortedVector : public std::vector<T> { /*.....*/ }
/* Hash for the key */
struct KeyHash : std::unary_function<Key, size_t> {
size_t operator()(Key const& x) const {
size_t hash = x.get<0>();
SortedVector<int>* xNumbers = x.get<2>();
if(xNumbers != NULL) {
BOOST_FOREACH(int num, *xNumbers) {
MurmurHash3_x86_32(&num, sizeof(size_t), hash, &hash);
}
}
return hash;
}
};
/* Equals for the key */
struct KeyEqual : std::binary_function<Key, Key, bool> {
size_t operator()(Key const& x, Key const& y) const {
if(x.get<0>() != y.get<0>() || fabs(x.get<1>() - y.get<1>()) > 0.00001 || x.get<3>() != y.get<3>()) {
return false;
}
SortedVector<int>* xNumbers = x.get<2>();
SortedVector<int>* yNumbers = y.get<2>();
if(xNumbers == yNumbers) {
return true;
}
if(xNumbers == NULL || yNumbers == NULL) {
return false;
}
if(xNumbers->size() != yNumbers->size()) {
return false;
}
return std::equal(xNumbers->begin(), xNumbers->end(), yNumbers->begin());
}
};
/* typedefs */
typedef boost::tuple<int, double, SortedVector<int>*, int> Key;
typedef boost::unordered_map<A, boost::unordered_map<Key, Value*, KeyHash, KeyEqual>, A::Hash, A::Equal> Map;
/* code that shows the problem */
void insertValues(A a, Key key, Value* value) {
Map::iterator iter = map->find(a);
if (iter == map->end()) {
iter = map.insert(std::make_pair(a, Map::value_type::second_type())).first;
}
Map::value_type::second_type::iterator keyIter = iter->second.find(key);
if (keyIter == iter->second.end()) {
iter->second.insert(std::make_pair(key, value));
}
}
скомпилирован с -O2
в keyIter
всегда равна iter->second.end()
, указывая, что key, value
пара не находится в карте , Однако при втором запуске insert
не вставляет пару. После консультации с boost documentation за insert
и find
Я пришел к выводу, что пока find
не находит пару, insert
находит и отклоняет ввод.
Скомпилировано с кодом -O1
код работает должным образом.
У кого-нибудь есть понимание, почему find
может давать разные результаты с -O1
и -O2
? Или почему результаты поиска find
и insert
могут отличаться?
Хеши используют MurmurHash3_x86_32 от MurmurHash3. Система представляет собой OpenSuse x86_64 GNU/Linux.
Что такое A, ключ и стоимость? Компилируемый пример очень поможет. – inf
Это пахнет неопределенным поведением, вы можете показать нам свой хэш и равные методы для начала? –
Операции хэша и равенства будут иметь решающее значение. SSCCE должен будет обнаружить любой UB в окружающем коде – sehe