【发布时间】:2012-12-09 17:39:00
【问题描述】:
这只是创建一些列表元素,然后在开始通过反向迭代接近它时删除一个元素。这是一个实际问题的复制品,即在反向遍历元素时删除元素的代码。
#include <list>
int main()
{
std::list< int > lst;
for ( int c = 33; c--; )
lst.push_back( 0 );
int count = 0;
for ( std::list< int >::reverse_iterator i = lst.rbegin(), e = lst.rend();
i != e; )
{
switch( count++ )
{
case 32:
case 33:
++i;
i = std::list< int >::reverse_iterator( lst.erase( i.base() ) );
break;
default:
++i;
}
}
return 0;
}
运行时会崩溃:
*** glibc detected *** ./a.out: double free or corruption (out): 0x00007fff7f98c230 ***
当使用 valgrind 运行时,它会说:
==11113== Invalid free() / delete / delete[] / realloc()
==11113== at 0x4C279DC: operator delete(void*) (vg_replace_malloc.c:457)
==11113== by 0x40104D: __gnu_cxx::new_allocator<std::_List_node<int> >::deallocate(std::_List_node<int>*, unsigned long) (in /tmp/a.out)
==11113== by 0x400F47: std::_List_base<int, std::allocator<int> >::_M_put_node(std::_List_node<int>*) (in /tmp/a.out)
==11113== by 0x400E50: std::list<int, std::allocator<int> >::_M_erase(std::_List_iterator<int>) (in /tmp/a.out)
==11113== by 0x400BB6: std::list<int, std::allocator<int> >::erase(std::_List_iterator<int>) (in /tmp/a.out)
==11113== by 0x40095A: main (in /tmp/a.out)
编译器:
$ g++ --version
g++ (Debian 4.7.1-7) 4.7.1
拱门:
$ uname -a
Linux hostname 3.2.0-2-amd64 #1 SMP Mon Apr 30 05:20:23 UTC 2012 x86_64 GNU/Linux
你认为这是一个错误,还是我在这里做错了什么?
附言如果您删除 case 33(这绝不应该发生),这将变成无限循环而不是崩溃。
【问题讨论】:
-
count中是否存在 off by 1 错误? (应该是switch(++count)?) -
否 - 循环的退出条件是
i != e,它不依赖于计数。 -
那是 - 它被关闭了,但它不应该导致任何问题。但是,由于内存损坏,迭代实际上继续超过 32。我已经编辑了这个问题,以便更清楚地说明这一点。
-
您在执行
lst.erase(i.base())时更新i,但您可能还需要更新e或简单地使用i != lst.rend()作为您的for终止条件(手头没有编译器验证)。 -
@ChrisSchmich:但为什么
e会失效?它指向第一个元素之前。