[C++] Vector Erase시 Segmentation Fault
Vector std library를 사용하다가 다음과 같은 코드에서 runtime error가 발생했다.
#include <iostream> #include <vector> using namespace std; int main() { vector<int> list; list.push_back(1); list.push_back(2); for (vector<int>::iterator iter=list.begin(); iter<list.end(); iter++) { if (*iter == 1) { list.push_back(3); iter = list.erase(iter); break; } else { iter++; } } return 0; }
Segmentation fault (core dumped)
원인을 분석하다가 erase()
함수 전에 push_back()
을 호출하여 vector에 element를 추가할 경우 문제가 되는 조건을 확인했다.
(gdb) bt #0 0x000000381e489d44 in _wordcopy_fwd_dest_aligned () from /lib64/libc.so.6 #1 0x000000381e4838be in memmove () from /lib64/libc.so.6 #2 0x0000000000401899 in std::__copy_move<false, true, std::random_access_iterator_tag>::__copy_m<int> (__first=0x603034, __last=0x60301c, __result=0x603030) at /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_algobase.h:378 #3 0x00000000004017ba in std::__copy_move_a<false, int*, int*> (__first=0x603034, __last=0x60301c, __result=0x603030) at /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_algobase.h:397 #4 0x000000000040159c in std::__copy_move_a2<false, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > > > (__first=0, __last=0, __result=0) at /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_algobase.h:436 #5 0x00000000004012ae in std::copy<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > > > (__first=0, __last=0, __result=0) at /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_algobase.h:468 #6 0x0000000000400d8a in std::vector<int, std::allocator<int> >::erase (this=0x7fffffffc220, __position=0) at /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/vector.tcc:137 #7 0x0000000000400a26 in main () at test.cpp:14
Solution
해결 방안으로 erase()
와 push_back()
호출 순서를 변경하니 문제가 해결됐다. 정확한 원인은 파악하지 못했다. Iteration을 하는 도중 push_back()
을 하게되면 erase()
호출 내부 코드에서 문제가 발생하는 것 같다.
(Update) 어느 좋은 분께서 comment로 답을 알려주셨는데, vector internal buffer size가 어느정도 커지면 새로운 큰 크기의 buffer로 옮긴다고 합니다.
#include <iostream> #include <vector> using namespace std; int main() { vector<int> list; list.push_back(1); list.push_back(2); for (vector<int>::iterator iter=list.begin(); iter<list.end(); iter++) { if (*iter == 1) { iter = list.erase(iter); list.push_back(3); break; } else { iter++; } } return 0; }
2 Comments
randomguy
원인이 여기에서 설명되어 있네요
https://stackoverflow.com/a/39360637
shumin
감사합니다, 생각해보니 vector structure 자체가 element가 증가하면 증가 할 수록 buffer capacity를 증가시킨다고 들은게 생각나네요.