i have a Problem regarding UNORDERED_MAP
im using these two typedefs:
typedef UNORDERED_MAP<uint32, WorldSession*> SessionCharMap;
typedef UNORDERED_MAP<uint32, SessionCharMap > SessionMap;
which are using following define:
# define UNORDERED_MAP stdext::hash_map
So basicly thats 1 container containing many containers of the other type SessionMap -*> SessionCharMap.
in following m_sessions is used:
SessionMap m_sessions;
Its used to assign a Sessionid several subids to handle them differently.
If the uint32 of SessionCharMap == NULL the Account is not yet fully logged in and has to choose a Character. This works fine, till i want to deassign a logged in Session to a not fully logged in Session:
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;
}
This code seam to break my m_sessions variable because the iterration Loop running over it to update Sessions does not terminate anymore.
I want to mention that i already tried “itr2->second[NULL] = ses;”
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++;
}
}
Following Debugoutput i get:
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
The i and j counter is only for the debugoutput. You can see the j counter going up for the inner Container. But i have only 1 Session online. If i want to logout it results in j going up to ~400 reading random memory ;-).
I dont understand why the for-loop
for (SessionCharMap::iterator itr = itr2->second.begin(); itr != itr2->second.end(); itr++){...}
runs over its boundaries. Please tell me if you found the mistake i am out of ideas.
And another thing: the UpdateSession Routine works fine when logged in correctly(only one iteration per for-loop). The Error first occurs when logging out. Then the iterrator goes crazy. My guess is, that i misshandled the container in DeassignCharFromSession.
UPDATE with help of you guys:
Corrected 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++;
}
}
Corrected 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;
}
But the Problem remains: The loop in UpdateSessions keeps iterating over the unordered_map. It happens 348 times and then ends with an Accessviolation.
And im still confused why
if(!itr->second){..}
triggers. since there should be only one valid session in the unordered_map.
When you use erase you are invalidating the iterator. So when you write
in
UpdateSessionsyou can no longer useitras it no longer points to a member of your hash map. So both the next linedelete itr->second;and crucially the loop iteration++itrare errors. The first problem is easily fixed, just switch the order of the delete and the eraseThe second problem is a little trickier, basically you have to rewrite your loop like this
This way you increment the iterator before you call erase but because you use the post-increment operator erase still gets the previous value of the iterator.