역 multi_index I 다음 (간체) 코드를 가지고 :부스트는 반복자 삭제 문제
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
namespace bmi = boost::multi_index;
#include <string>
#include <iostream>
#include <cassert>
using Container = boost::multi_index_container<
std::string,
bmi::indexed_by< bmi::ordered_non_unique< bmi::identity<std::string> > >
>;
/// Get the base of a non-reverse iterator. It's the iterator itself.
inline
Container::iterator const&
iter_base(Container::iterator const& it)
{
return it;
}
/** Get a non-reverse iterator that points at the same element as the given reverse_iterator.
*
* @param rit reverse_iterator
* @return a (non-reverse) iterator that points to the same element.
* @pre @p rit is dereferenceable (not equal to @c rend() of whatever container @p rit came from)
*/
inline
Container::iterator
iter_base(Container::reverse_iterator const& rit)
{
auto bit = rit.base();
// if 'rit' is a reverse iterator: &*(rit.base() - 1) == &*rit
return --bit;
}
template <typename IT>
void evict(Container& c, IT rb, IT fin)
{
std::vector<std::string> result;
for (; rb != fin;) {
if (rb->size() == 3) {
auto victim = rb;
++rb;
std::cout << "victim->" << *victim << ", next->" << (rb==fin ? std::string{"THE END"} : *rb) << "\n";
auto next = c.erase(iter_base(victim));
std::cout << "size=" << c.size() << "\n";
for (auto const& s : c) {
std::cout << "remain: " << s << "\n"; // bar - baz - foo
}
rb = IT(next);
(void)next;
}
else {
result.push_back(*rb);
}
}
}
int main(int argc, char**)
{
bool forward = (argc == 1);
Container c;
c.insert("foo"); // will be last
c.insert("bar");
c.insert("baz");
if (forward) {
auto b = c.lower_bound("baz");
std::cout << ">> " << *b << "\n"; // prints baz
auto rb = (b);
std::cout << "<< " << *rb << "\n"; // prints baz
std::cout << "<< " << *iter_base(rb) << "\n"; // prints baz
evict(c, rb, c.end());
}
else {
auto b = c.upper_bound("baz");
std::cout << ">> " << *b << "\n"; // prints foo
auto rb = Container::reverse_iterator(b);
std::cout << "<< " << *rb << "\n"; // prints baz
std::cout << "<< " << *iter_base(rb) << "\n"; // prints baz
evict(c, rb, c.rend());
}
}
실제 코드를 그냥 삭제보다 더 많은 작업을 수행하지만이 동작을 설명하기에 충분하다.
루프에서 제거가 발생하지 않는다는 것을 보여주기 위해 EDITED가 표시됩니다. 항목은 사용 된 반복기 종류에 따라 순방향 또는 역순으로 result
에 추가되어야합니다.
는 인수없이 실행하면 forward==true
및 출력이 예상대로 :
>> baz
<< baz
<< baz
victim->baz, next->foo
size=2
remain: bar
remain: foo
victim->foo, next->THE END
size=1
remain: bar
인수, forward==false
으로 실행하고 출력 인 경우 :
>> foo
<< baz
<< baz
victim->baz, next->bar
size=2
remain: bar
remain: foo
segmentation fault (core dumped)
(예상대로되지 않음)
주소 살균기로 컴파일하면 42 행 (++ rb 행)에 heap-after-free가 표시됩니다.
지우기가 다른 이터레이터를 무효로하지 않아도 되겠지만, erase(victim)
을 호출하면 어떤 식 으로든 rb
이 무효화 된 것처럼 보입니다.
내가 뭘 잘못하고 있는지 아는 사람이 있습니까?
불행히도, 이것은 도움이되지 않습니다. heap-after-after free는'++ next' 라인에 남아 있습니다. – Bulletmagnet
제안 된 코드 *를 그대로 복사 한 적이 있습니까? 예를 들어'if (rb! = fin) for (;;)'부분에 유의하십시오. –
죄송합니다. 제안 된 솔루션은 실제로 결함이 있습니다. 희망에 따라 올바른 대안으로 수정되었습니다. –