2012-05-27 193 views
2

我正在嘗試使用地圖系統來存儲和更新聊天服務器的數據。該應用程序是多線程的並使用鎖定系統來防止多線程訪問數據。C++映射迭代和堆棧損壞

問題是這樣的:當一個客戶端被單獨從地圖中刪除時,就沒關係。但是,當我嘗試調用多個關閉時,它會在內存中留下一些內容。如果我在地圖上的任何一個地方調用:: clear(),它會導致一個調試斷言錯誤,或者「迭代器不兼容」或類似。代碼將第一次運行(使用80+控制檯作爲測試連接進行測試),但由於它將塊放在後面,將不再工作。我已經嘗試過研究方法,並且我已經編寫了系統來停止代碼執行,直到每個進程完成。我非常感謝迄今爲止所提供的幫助,並附上了相關的代碼片段。

//portion of server code that handles shutting down 
DWORD WINAPI runserver(void *params) { 
    runserverPARAMS *p = (runserverPARAMS*)params; 
    /*Server stuff*/        

    serverquit = 0; 
    //client based cleanup 
    vector<int> tokill; 
    map<int,int>::iterator it = clientsockets.begin(); 

    while(it != clientsockets.end()) {  
     tokill.push_back(it->first); 
     ++it; 
    } 
    for(;;) { 
     for each (int x in tokill) { 
      clientquit[x] = 1; 
      while(clientoffline[x] != 1) { 
       //haulting execution until thread has terminated 
      } 
      destoryclient(x); 
     } 
    } 
    //client thread based cleanup complete. 
    return 0; 
} 


//clientioprelim 
DWORD WINAPI clientioprelim(void* params) { 
    CLIENTthreadparams *inparams = (CLIENTthreadparams *)params; 
    /*Socket stuff*/ 
    for(;;) {  
     /**/ 
     } 
     else { 
      if(clientquit[inparams->clientid] == 1) 
       break; 
     } 
    } 
    clientoffline[inparams->clientid] = 1; 
    return 0; 
} 

int LOCKED; //exported as extern via libraries.h so it's visible to other source files 

void destoryclient(int clientid) { 
    for(;;) { 
     if(LOCKED == 0) { 
      LOCKED = 1;   
      shutdown(clientsockets[clientid], 2); 
      closesocket(clientsockets[clientid]); 
      if((clientsockets.count(clientid) != 0) && (clientsockets.find(clientid) != clientsockets.end())) 
       clientsockets.erase(clientsockets.find(clientid));     
      if((clientname.count(clientid) != 0) && (clientname.find(clientid) != clientname.end())) 
       clientname.erase(clientname.find(clientid)); 
      if((clientusername.count(clientid) != 0) && (clientusername.find(clientid) != clientusername.end())) 
       clientusername.erase(clientusername.find(clientid)); 
      if((clientaddr.count(clientid) != 0) && (clientaddr.find(clientid) != clientaddr.end())) 
       clientaddr.erase(clientusername.find(clientid)); 
      if((clientcontacts.count(clientid) != 0) && (clientcontacts.find(clientid) != clientcontacts.end())) 
       clientcontacts.erase(clientcontacts.find(clientid)); 
      if((clientquit.count(clientid) != 0) && (clientquit.find(clientid) != clientquit.end())) 
       clientquit.erase(clientquit.find(clientid));  
      if((clientthreads.count(clientid) != 0) && (clientthreads.find(clientid) != clientthreads.end())) 
       clientthreads.erase(clientthreads.find(clientid)); 
      LOCKED = 0; 
      break;   
     } 
    } 
    return; 
} 
+0

這是什麼語言有'每個'? –

+0

我的'Visual C++'用''爲每個'做了'... – IAbstract

+1

Visual C++對每個'擴展名都有一個非標準的':http://msdn.microsoft.com/en-us/library/xey702bw%28VS。 80%29.aspx –

回答

0

您確實在使用int進行鎖定,還是僅僅是簡化了代碼?如果您確實使用了int:如果兩個線程在分配變量(簡化)之前檢查該變量,則這將不起作用,並且臨界區可以同時輸入兩次(或更多)。請參閱mutexes in Wikipedia以供參考。你可以使用Windows提供的某種互斥鎖,或者使用boost thread而不是int

+0

我實際上使用了一個int。我將更多地研究mutux對象(我發現了一些有關它的MSDN技巧)。 –

+0

是的,「每個」通過我。我總是習慣於「foreach」。 –

+0

工作!謝謝!我正在使用MUTEX函數和WaitForSingleObject,而不是用於客戶端線程終止的另一個映射。奇蹟般有效!非常感謝你! –