2012-09-08 2 views
0

나는 문제에 관한 unordered_map도중첩 stdext :: hash_map 반복

메신저이 두 형식 정의를 사용하여이 다른 유형의 많은 컨테이너를 포함하는 SessionMap ->> SessionCharMap. 다음 m_sessions에서

이 사용됩니다

SessionMap m_sessions;  

자사가 다르게 처리하는 SESSIONID 여러 subids을 지정하는 데 사용됩니다. uint32가 SessionCharMap == NULL 인 경우 계정이 아직 완전히 로그인되어 있지 않으므로 문자를 선택해야합니다. 나는 완전히 세션에 기록되지 않은에 세션에 로그인 할당 해제 할 때까지이 잘 작동 :

bool DeassignCharFromSession(uint32 acc, uint32 chr){ 

SessionMap::iterator itr2; 
for (itr2 = m_sessions.begin(); itr2 != m_sessions.end(); itr2++){  
    if(itr2->first == acc){ 
     for (SessionCharMap::iterator itr = itr2->second.begin(); itr != itr2->second.end(); itr++){ 
      if(itr->first == chr && 
       itr->second){ 
       WorldSession* ses = itr->second;                          
       itr2->second.erase(itr); 
       m_sessions[acc][NULL] = ses; 
       sLog.outDebug("############################################1 %d %d",itr2->first,itr->first); 

       return true; 
      } 
     } 
    } 
} 

return false; 
} 

iterration 루프가 세션이 더 이상 종료되지 않습니다 업데이트 할를 통해 실행하기 때문에 변수 내 m_sessions을 깰이 코드 심 . 나는 이미 "itr2-> second [NULL] = ses;"를 시도했다고 언급하고 싶습니다. "

2012-09-08 08:33:13 ############################################1 1 1 
012-09-08 08:33:13 ########################### 123 1 0 0 0 1 
2012-09-08 08:33:13 ########################### 1231 1 0 
2012-09-08 08:33:13 ########################### 123 1 0 0 0 2 
2012-09-08 08:33:13 ########################### 1231 1 0 
2012-09-08 08:33:13 ########################### 123 1 0 0 0 3 
2012-09-08 08:33:13 ########################### 1231 1 0 
2012-09-08 08:33:13 ########################### 123 1 0 0 0 4 
2012-09-08 08:33:13 ########################### 1231 1 0 
2012-09-08 08:33:13 ########################### 123 1 0 0 0 5 
2012-09-08 08:33:13 ########################### 1231 1 0 
2012-09-08 08:33:13 ########################### 123 1 0 0 0 6 
2012-09-08 08:33:13 ########################### 1231 1 0 
2012-09-08 08:33:13 ########################### 123 1 0 0 0 7 
2012-09-08 08:33:13 ########################### 1231 1 0 
2012-09-08 08:33:13 ########################### 123 1 0 0 0 8 
2012-09-08 08:33:13 ########################### 1231 1 0 
2012-09-08 08:33:13 ########################### 123 1 0 0 0 9 
2012-09-08 08:33:13 ########################### 1231 1 0 
2012-09-08 08:33:13 ########################### 123 1 0 0 0 10 
2012-09-08 08:33:13 ########################### 1231 1 0 
2012-09-08 08:33:13 ########################### 123 1 0 0 0 11 
2012-09-08 08:33:13 ########################### 1231 1 0 
2012-09-08 08:33:13 ########################### 123 1 0 0 0 12 
2012-09-08 08:33:13 ########################### 1231 1 0 
2012-09-08 08:33:13 ########################### 123 1 0 0 0 13 
2012-09-08 08:33:13 ########################### 1231 1 0 
2012-09-08 08:33:13 ########################### 123 1 0 0 0 14 
2012-09-08 08:33:13 ########################### 1231 1 0 
2012-09-08 08:33:13 ########################### 123 1 0 0 0 15 
2012-09-08 08:33:13 ########################### 1231 1 0 
2012-09-08 08:33:13 ########################### 123 1 0 0 0 16 
2012-09-08 08:33:13 ########################### 1231 1 0 
2012-09-08 08:33:13 ########################### 123 1 0 0 0 17 

I 및 J 카운터 만 debugoutput입니다 :

void UpdateSessions(uint32 diff) 
int i = 0; 
for (SessionMap::iterator itr2 = m_sessions.begin(); itr2 != m_sessions.end(); ++itr2){  
    int j = 0; 
    for(SessionCharMap::iterator itr = itr2->second.begin(); itr != itr2->second.end(); ++itr){ 
     //WorldSession * pSession = itr->second; 
     debug_log("########################### 123 %d %d %d %d %d",itr2->first,itr->first, itr->second ? 1 : 0, i,j); 
     j++; 
     WorldSessionFilter updater(itr->second); 

     if(!itr->second){ 
      debug_log("########################### 1231 %d %d",itr2->first,itr->first); 
      //itr2->second.erase(itr); 
     } else 
     if(!itr->second->Update(updater)) 
     { 
      debug_log("########################### 1233"); 
      RemoveQueuedSession(itr->second);        
      debug_log("########################### 1234"); 
      itr2->second.erase(itr); 
      debug_log("########################### 1235"); 
      delete itr->second;    
      debug_log("########################### 1236"); 
     }   
    } 
    i++; 
} 
} 

는 Debugoutput에 따라 내가 얻을. j 카운터가 내부 컨테이너로 올라가는 것을 볼 수 있습니다. 그러나 나는 단 하나의 세션을 온라인으로 가지고 있습니다. 로그 아웃하려면 j가 최대 400 개의 임의의 메모리 읽기 ;-)로 바뀝니다.

은 이해 해달라고 왜의 경계에 걸쳐위한 루프

for (SessionCharMap::iterator itr = itr2->second.begin(); itr != itr2->second.end(); itr++){...} 

실행됩니다. 제 생각이 틀린 실수를 발견하면 말해주십시오.

또 다른 한가지 : UpdateSession 루틴은 제대로 로그인하면 잘 작동합니다 (for-loop 당 하나의 반복 만). 오류는 먼저 로그 아웃 할 때 발생합니다. 그러면 이터레이터는 미쳐 버립니다. 내 생각 엔 DeassignCharFromSession의 컨테이너를 잘못 처리했다는 것입니다. 너희들의 도움으로

UPDATE :

수정 UpdateSession

void UpdateSessions(uint32 diff){ 
int i = 0; 
for (SessionMap::iterator itr2 = m_sessions.begin(); itr2 != m_sessions.end(); ++itr2){  
    int j = 0; 
    for(SessionCharMap::iterator itr = itr2->second.begin(); itr != itr2->second.end();){ 
     //WorldSession * pSession = itr->second; 
     debug_log("########################### 123 %d %d %d %d %d",itr2->first,itr->first, itr->second ? 1 : 0, i,j); 
     j++; 
     WorldSessionFilter updater(itr->second); 

     debug_log("########################### 123 %d %d %d",itr2->first,itr->first, itr->second ? 1 : 0); 
     if(!itr->second){ 
      //this case should never occur! 
      debug_log("########################### 1231 %d %d",itr2->first,itr->first); 
      ++itr; 
      //itr2->second.erase(itr); 
     }else 

     if(!itr->second->Update(updater)) 
     { 
      debug_log("########################### 1233"); 
      RemoveQueuedSession(itr->second);        
      debug_log("########################### 1234"); 
      delete itr->second; 
      debug_log("########################### 1235"); 
      itr2->second.erase(itr++); 
      debug_log("########################### 1236"); 
     } else { 
      ++itr; 
     } 
    } 
    i++; 
}   
} 

수정 DeassignCharFromSession :

bool DeassignCharFromSession(uint32 acc, uint32 chr){ 
if(m_sessions[acc][chr]){ 
    sLog.outDebug("############################################1 %d %d",acc,chr); 
    m_sessions[acc][NULL] = m_sessions[acc][chr]; 
    m_sessions[acc].erase(chr); 
    sLog.outDebug("############################################2"); 
    return true; 
} 

debug_log("################################### UUU2"); 
return false; 
} 

그러나 문제는 남아 : UpdateSessions의 루프는 unordered_map도 반복 유지합니다. 348 번 발생하고 액세스 위반으로 끝납니다. 그리고 메신저는 여전히 혼란스러워하는 이유

경우 (! itr-> 두번째) {...}

트리거. unordered_map에는 유효한 세션이 하나만 있어야하기 때문입니다.

+0

왜 처음에 m_sessions [acc] [chr] 함수에 내장 된 hash_map 대신 2 개의 루프를 사용하고 있습니까? –

+0

아아 멋지다 시도 할 것입니다, 그러나 그것은 내가 모든 로그인 된 세션을 반복해야하기 때문에 삭제 부분에만 작동합니다. – Dornhoeschen

답변

0

지우기를 사용하면 이터레이터이 무효화됩니다. 당신이 UpdateSessions

itr2->second.erase(itr); 

을 쓸 때 그래서 당신은 더 이상 해시 맵의 멤버로로 더 이상 포인트를 itr을 사용할 수 없습니다. 그러므로 다음 줄인 delete itr->second;과 루프 반복문 ++itr은 모두 오류입니다. 첫 번째 문제는 쉽게 다만 기본적으로이

for (SessionCharMap::iterator itr = itr2->second.begin(); itr != itr2->second.end();) 
{ 
    ... 
    if (itr->second->Update(updater)) 
    { 
     ++itr; 
    } 
    else 
    { 
     ... 
     delete itr->second; 
     itr2->second.erase(itr++); 
    } 
} 

이 방법처럼 루프를 다시 작성해야, 삭제의 순서와 삭제

delete itr->second; 
itr2->second.erase(itr); 

두 번째 문제는 조금 까다 롭습니다를 전환, 고정 을 증가시키고 전에 지우기를 호출하지만 사후 증가 연산자 지우기를 사용하기 때문에 여전히 이터레이터의 이전 값을 가져옵니다.

+0

감사합니다. 문제의 일부를 해결했다고 생각합니다. 여전히 j는 348 번 증가합니다. 여기서 1x 만 증가해야합니다. 문제의 코드 수정 ;-) – Dornhoeschen

0

문제가 해결되었습니다. DeassignCharFromSession의 삭제로 인해 UpdateSessions (아래 참조)의 반복자가 유효하지 않게됩니다. 휴식을 통해 해결되었습니다. 이렇게하면 일부 세션에서 업데이트를 위해 2 사이클을 대기하게됩니다.

///- Then send an update signal to remaining ones 
debug_log("############################## OOOOO LOL"); 
int i = 0; 
for (SessionMap::iterator itr2 = m_sessions.begin(); itr2 != m_sessions.end(); ++itr2){  
    int j = 0; 
    SessionCharMap::iterator itr; 
    for(itr = itr2->second.begin(); itr != itr2->second.end();){ 
     //WorldSession * pSession = itr->second; 
     debug_log("########################### 123 %d %d %d %d %d",itr2->first,itr->first, itr->second ? 1 : 0, i,j); 
     j++; 
     WorldSessionFilter updater(itr->second); 

     debug_log("########################### 123 %d %d %d",itr2->first,itr->first, itr->second ? 1 : 0); 
     if(!itr->second){ 
      //this case should never occur! but it does cuz iterator becomes invalid cuz of delete 
      debug_log("########################### 1231 %d %d",itr2->first,itr->first); 
      ++itr; 
      break; 
      //itr2->second.erase(itr); 
     }else 

     if(!itr->second->Update(updater)) 
     { 
      debug_log("########################### 1233"); 
      RemoveQueuedSession(itr->second);        
      debug_log("########################### 1234"); 
      delete itr->second; 
      debug_log("########################### 1235"); 
      itr2->second.erase(itr++); 
      debug_log("########################### 1236"); 
     } else { 
      ++itr; 
     } 
    } 
    i++; 
} 
관련 문제