2015-12-31 4 views
0

Я получаю странную ошибку ошибки сегментации при стирании элемента в векторе. Это код:SIGSEGV в Vector.erase

int i = 0; 
    cout << "SIZE: " << OrderList::sellOrders.size(); 
    for(vector<Order>::iterator it = OrderList::sellOrders.begin(); it != OrderList::sellOrders.end(); it++, i++) 
    { 
     if(OrderList::sellOrders[i].pThis->usesWamp() == false) 
     { 
      cout << "Erase element " << i << endl; 
      OrderList::sellOrders.erase(it); 
     } 
    } 

Выход заключается в следующем:

SIZE: 44 
Erase element 0 
Erase element 2 
Erase element 3 
Erase element 4 
Erase element 5 
Erase element 6 
Erase element 7 
Erase element 8 
Erase element 9 
Erase element 10 
Erase element 11 
Erase element 12 
Erase element 13 
Erase element 14 
Erase element 15 
Erase element 16 
Erase element 17 
Erase element 18 
Erase element 19 
Erase element 20 
Erase element 21 
Erase element 22 
Erase element 23 

Program received signal SIGSEGV, Segmentation fault. 
__memmove_ssse3_back() at ../sysdeps/x86_64/multiarch/memcpy-ssse3-back.S:1548 
1548 ../sysdeps/x86_64/multiarch/memcpy-ssse3-back.S: No such file or directory. 
(gdb) 
(gdb) where 
#0 __memmove_ssse3_back() 
    at ../sysdeps/x86_64/multiarch/memcpy-ssse3-back.S:1548 
#1 0x0000000000485d48 in std::__copy_move<true, true, std::random_access_iterator_tag>::__copy_m<Order> (__first=0x7fffe400e4a0, __last=0x7fffe400e470, 
    __result=0x7fffe400e488) at /usr/include/c++/4.8/bits/stl_algobase.h:372 
#2 0x00000000004807c4 in std::__copy_move_a<true, Order*, Order*> (
    __first=0x7fffe400e4a0, __last=0x7fffe400e470, __result=0x7fffe400e488) 
    at /usr/include/c++/4.8/bits/stl_algobase.h:390 
#3 0x000000000047879f in std::__copy_move_a2<true, __gnu_cxx::__normal_iterator<Order*, std::vector<Order, std::allocator<Order> > >, __gnu_cxx::__normal_iterator<Order*, std::vector<Order, std::allocator<Order> > > > (__first=..., 
    __last=..., __result=...) at /usr/include/c++/4.8/bits/stl_algobase.h:428 
#4 0x000000000046f9d3 in std::move<__gnu_cxx::__normal_iterator<Order*, std::vector<Order, std::allocator<Order> > >, __gnu_cxx::__normal_iterator<Order*, std::vector<Order, std::allocator<Order> > > > (__first=..., __last=..., 
    __result=...) at /usr/include/c++/4.8/bits/stl_algobase.h:492 
#5 0x0000000000467754 in std::vector<Order, std::allocator<Order> >::erase (
    this=0x6c7c10 <OrderList::sellOrders>, __position=...) 
    at /usr/include/c++/4.8/bits/vector.tcc:138 
#6 0x0000000000421320 in OrderList::flush() at ../Bether/OrderList.h:339 
#7 0x000000000044b12a in main() at ../Bether/main.cpp:354 

Таким образом, вы можете видеть вектор имеет 44 элементов (SIZE: 44), но терпит неудачу, когда элемент 23 должен быть удален.

ответ

6

std::vector::erase() аннулирует итератора, а это означает, что не определено поведение разыменовать его (*it) или увеличить его (++it) после этого.

Хорошая и обычная парадигма сочетать std::remove_if(), которая перемещает быть удалены элементы в задней части контейнера для std::vector::erase(), чтобы фактически удалить их:

std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6 }; 
v.erase(std::remove_if(v.begin(), v.end(), [](int n){ return n%2==0; }), v.end()); 
// v is { 1, 3, 5 } 
+0

@TommyA опечатка исправлена. Спасибо. – YSC

3

Функция erase делает недействительными итераторы и ссылки, указывающие после стертого положения.

Если вы действительно хотели их стереть, вы можете изменить цикл для повторения в порядке убывания, это не должно быть проблемой, поскольку вы используете векторы, которые могут легко разрешать двунаправленные входы. Таким образом, только ссылки на уже проверенные местоположения будут признаны недействительными.

Смежные вопросы