2014-11-09 2 views
2

최근에 나는 erase 메서드로 인한 unordered_set의 이상한 동작을 발견했습니다. 나는 아래에 최소한의 예를 제시한다.unordered_map 지우기 segfault

먼저 unordered_set을 만듭니다. 그런 다음 요소 중 하나 인 프랑스를 지 웁니다. 그런 다음 for 루프를 사용하여 모든 요소를 ​​지 웁니다. 실행시, segfaults. 그러나 내가 지우는 프랑스 부분을 주석 처리하면 코드가 제대로 작동합니다.

이 프로그램은 g++ test.cpp --std=c++11으로 컴파일됩니다. g ++의 버전은 4.9.1입니다.

#include <iostream> 
#include <string> 
#include <unordered_set> 

int main() 
{ 
    std::unordered_set<std::string> myset = 
    {"USA","Canada","France","UK","Japan","Germany","Italy"}; 

    // erasing by key, causing segfault later; no segfault if commented out 
    myset.erase ("France");       

    std::cout << "myset contains:"; 
    for (const std::string& x: myset) { myset.erase(x); } 

    // The problem persists for a regular for loop as well. 
    //for ( std::unordered_set<std::string>::iterator it = myset.begin(); it!=myset.end(); it++ ) { myset.erase(it); } 

    std::cout << std::endl; 

    return 0; 

} 

단서가 있습니까?

감사 범위 기반 루프가 정의되지 않은 동작하는 내부 KC

답변

6

소거 요소. 세트에서 요소를 지울 때 해당 요소에 대한 반복자는 무효화되고 컴파일러는 현재 요소의 반복자를 사용하여 다음 요소로 진행합니다. 요소가 삭제 된 시간 ++__begin에서

auto && __range = range-init; 
for (auto __begin = begin-expr(__range), 
    __end = end-expr(__range); 
    __begin != __end; 
    ++__begin) { 
    for-range-declaration = *__begin; 
    statement 
} 

가 호출되고 반복자는 유효하지 않습니다 기반의 범위에 해당합니다.

편집 : 여기 당신을 제대로 할 수있는 방법의 예 : C++ 11 erase 방법은 새로운 반복자를 반환에서

auto it = myset.begin(); 
while (it != myset.end()) { it = myset.erase(it); } 

, 그래서이가 가리키는 요소 후 이전 반복자를 증가 방지 지워졌습니다. 그러나이 코드는 단지 실험이 아니라면 꽤 의미가 없습니다. 세트 내용을 지우려면 myset.clear()으로 전화하십시오.

+0

답장을 보내 주셔서 감사합니다. Jonathan. 나는 range-for for 루프를 일반적인 for 루프로 대체하려고 시도했지만 문제는 여전히 지속된다. 원본 게시물을 수정하십시오. –

+0

@ K.Chen : 귀하의 편집은 range 기반의 작업과 정확히 동일합니다. 즉, 유효하지 않은 반복기에 의존합니다. 어떻게하면이 문제를 해결할 수 있는지에 대한 답을 보여주는 예제를 추가 할 것입니다. –