C / C++,  Programming

[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

Leave a Reply

Your email address will not be published. Required fields are marked *