2017-11-01 3 views
-4

다른 목록의 사본 인 목록을 만들었습니다. 이 목록은 복사 됨으로 불립니다. 복사 된 숫자의 목록을 섞어서 만들려고합니다. 사용자는 초기 목록의 크기 (원하는 카드 수)를 입력하고 목록이 작성되고 여기에서 목록이 섞여서 사용됩니다. 하지만 사용자가 20 이상을 입력하면 어떤 이유로이 오류가 발생합니다.std :: list items 지울 때 버그가 발생했습니다.

output(41432,0x7fff7389e000) malloc: *** error for object 0x7fff55638490: 
pointer being freed was not allocated 
*** set a breakpoint in malloc_error_break to debug 
Abort trap: 6 

다음은 내 코드 섹션입니다. while (! copied.empty()) 루프를 제거하면 초기 목록의 "r"위치에 "it"값을 새 목록으로 넣는 것처럼 잘 작동합니다. 하지만 각 "r"에 대해이 작업을 수행해야합니다.

list<size_t> copied; 
    copied.insert(copied.end(), cards.begin(), cards.end()); 
    int r = rand()%(((copied.size()+1) - 0) + 1) + 0; 

    list<size_t>::const_iterator it = copied.begin(); 

    while(!copied.empty()){ 
     for(int i = 0; i < r; i++) { 
      it++;} 
     shuffle.push_back(*it); 
     copied.erase(it);} 
+2

'it'을하는'목록 ​​ :: const_iterator'로 정의하면서하는' std :: list''erase()'메서드는'iterator'에 대해서만 정의됩니다. iterator와 const_iterator는 구별되는 타입이다. 또한 반복되는 동안 목록에서 요소를 제거하는 방법에 대한이 질문을 참조하십시오. https://stackoverflow.com/questions/596162/can-you-remove-elements-from-a-stdlist-while-iterating-through-it – Polb

+0

(1 + 1-0 + 1)은 3이므로 r은 0과 2 사이의 어떤 값이 될 수 있으므로'copied.begin()'은 0으로 설정된다. 0 번에서 2 번까지 어디서든 증가 할 수 있습니다. 'copying.begin()'을 한 번만 증가시키고, 그것을 역 참조하려고 시도하고, 의미있는 결과를 기대하는 행운을 비네. 문제는 기본 수학이며, 반복기 및 0 기반 배열/컨테이너 인덱싱 작업에 대한 더 나은 이해가 필요합니다. –

+1

또한,'erase'는 반복자를 무효화합니다. 당신은 그때 그것을 증가시킬 수없고 목록의 나머지 부분에 돌아올 것으로 기대합니다. – Beta

답변

3

문제는 copied.erase(it) 반복자 it을 무효화한다는 것입니다, 그래서 그것의 후속 사용은 정의되지 않은 동작입니다. 하나가 삭제 된 후 대신 다음 요소로

it = copied.erase(it); 
if (it == copied.end()) it = copied.begin(); 

erase 이후 반환하는 유효한 반복자를 사용할 수 있습니다. 즉 아마이어야한다, 그래서 당신은 또한,리스트의 마지막 떨어져 실행 for 루프에서 it++에 대해 걱정할 필요가 :

for(int i = 0; i < r; i++) { 
    if (++it == copied.end()) 
     it = copied.begin(); } 
+0

아니요,이 대답은 잘못되었습니다. 표시된 코드를 자세히 검토하십시오. 표시된 코드에서 깨진 들여 쓰기 때문에이 방법으로 만 보입니다. 'erase();'는 바깥 쪽 루프 만 끝내고, 모든 반복자가'erase()'전에 일어나고, 그 자체로 증가 점이 문제가되어 컨테이너의 끝을 벗어납니다. 이것은 단지 나쁜 질문입니다. –

+0

@SamVarshavchik : 나는 게시 된 코드의 내용으로 만 갈 수 있습니다. 의미 론적으로 말도 안되는 경우에는 구문 상 정확합니다. '지우기'는 루프를 종료하지 않습니다. 루프는 지우기 후에 계속되고 다시 루핑됩니다. –

+0

정확히 게시 된 코드입니다. 게시 된 코드는 무효화 된 반복자를 증가시키지 않습니다. 점증하는 자체는'erase()'이전에 반복자를 무효화했다. 'erase();'는 *** outer *** while 루프를 끝냅니다. 중괄호를 센다. –

관련 문제