У меня есть следующий метод в C++
, который удаляет только элементы, связанные с определенным tableId
с карты.Итерация по карте C++, дающая бесконечный цикл
69 void
70 ObjectFinder::flush(uint64_t tableId) {
71
72 RAMCLOUD_TEST_LOG("flushing object map");
74 // find everything between tableId, 0
75 // keep scanning util find all the entries for that table
76 std::map<TabletKey, ProtoBuf::Tablets::Tablet>::const_iterator it;
79 for (it = tableMap.begin(); it != tableMap.end(); it++) {
80 TabletKey current = it->first;
81 if (tableId == current.first) {
82 tableMap.erase(current);
83 }
84 }
85 std::cout << "hello" << std::endl;
87 }
Шагая в код с gdb
я обнаружил, что бесконечный цикл происходит после итерации цикла for
. Строка 85
никогда не печатается. Я предполагаю, что свисающий указатель происходит. В первом цикле элемент current
удален, а затем в следующих двух ничего не происходит, а затем у меня есть бесконечный цикл. Я не знаю, почему это происходит. У кого-то есть идея или она испытала это раньше?
Еще умнее версия моего кода является использование lower_bound
и upper_bound
, чтобы найти, где id
начинается (это позволит сэкономить некоторое вычислительное время):
69 void
70 ObjectFinder::flush(uint64_t tableId) {
71
72 RAMCLOUD_TEST_LOG("flushing object map");
KeyHash keyHash = Key::getHash(tableId, "", 0);
74 // find everything between tableId, 0
75 // keep scanning util find all the entries for that table
76 std::map<TabletKey, ProtoBuf::Tablets::Tablet>::const_iterator lower;
std::map<TabletKey, ProtoBuf::Tablets::Tablet>::const_iterator upper;
TabletKey key(tableId, keyHash);
lower = tableMap.lower_bound(key);
upper = tableMap.upper_bound(key);
tableMap.erase(lower, upper);
85 std::cout << "hello" << std::endl;
87 }
и я получаю:
/home/ribeiro.phillipe/ramcloud/src/ObjectFinder.cc:81: error: no matching function for call to ‘std::map<std::pair<long unsigned int, long unsigned int>, RAMCloud::ProtoBuf::Tablets_Tablet, std::less<std::pair<long unsigned int, long unsigned int> >, std::allocator<std::pair<const std::pair<long unsigned int, long unsigned int>, RAMCloud::ProtoBuf::Tablets_Tablet> > >::erase(std::_Rb_tree_const_iterator<std::pair<const std::pair<long unsigned int, long unsigned int>, RAMCloud::ProtoBuf::Tablets_Tablet> >)’
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_map.h:566: note: candidates are: void std::map<_Key, _Tp, _Compare, _Alloc>::erase(typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator) [with _Key = std::pair<long unsigned int, long unsigned int>, _Tp = RAMCloud::ProtoBuf::Tablets_Tablet, _Compare = std::less<std::pair<long unsigned int, long unsigned int> >, _Alloc = std::allocator<std::pair<const std::pair<long unsigned int, long unsigned int>, RAMCloud::ProtoBuf::Tablets_Tablet> >]
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_map.h:581: note: typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::size_type std::map<_Key, _Tp, _Compare, _Alloc>::erase(const _Key&) [with _Key = std::pair<long unsigned int, long unsigned int>, _Tp = RAMCloud::ProtoBuf::Tablets_Tablet, _Compare = std::less<std::pair<long unsigned int, long unsigned int> >, _Alloc = std::allocator<std::pair<const std::pair<long unsigned int, long unsigned int>, RAMCloud::ProtoBuf::Tablets_Tablet> >]
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_map.h:596: note: void std::map<_Key, _Tp, _Compare, _Alloc>::erase(typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator, typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator) [with _Key = std::pair<long unsigned int, long unsigned int>, _Tp = RAMCloud::ProtoBuf::Tablets_Tablet, _Compare = std::less<std::pair<long unsigned int, long unsigned int> >, _Alloc = std::allocator<std::pair<const std::pair<long unsigned int, long unsigned int>, RAMCloud::ProtoBuf::Tablets_Tablet> >]
make: *** [obj.master/ObjectFinder.o] Error 1
является потому что у меня нет версии C++
, которая поддерживает это?
При удалении элемента с карты итератор недействителен. Вы можете «tableMap.erase (current ++)» (постинъекция важна) с циклом while – nijansen