2

マップのシステムを使用して、チャット サーバーのデータを保存および更新しようとしています。アプリケーションはマルチスレッド化されており、ロック システムを使用して複数のスレッドがデータにアクセスするのを防ぎます。

問題は次のとおりです。クライアントがマップから個別に削除されても問題ありません。ただし、複数のクローズを呼び出そうとすると、一部がメモリに残ります。マップ上でいつでも ::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;
}
4

1 に答える 1

0

本当にintロックにを使用していますか、それともコードを単純化しただけですか?実際に:を使用する場合、intこれは機能せず、クリティカルセクションを同時に2回(またはそれ以上)入力できます。両方のスレッドが変数を割り当てる前に変数をチェックする場合(簡略化)。参照については、ウィキペディアのミューテックスを参照してください。の代わりに、Windowsが提供するある種のミューテックスを使用するか、スレッドをブーストintすることができます。

于 2012-05-27T02:28:58.647 に答える