2000 Subj : problem with STL containers To : borland.public.cpp.borlandcpp From : zero Date : Tue Apr 13 2004 01:56 pm First a short discription of my program. I have a bot that connects to an internet chess server. Whenever the bot logs on, it loads certain information from file, and puts it in STL containers (specifically sets & maps). When disconnecting for any reason, the containers are converted to strings, and saved to disk, so they can be loaded again when the bot logs back on. Periodically (triggered by a timer event), the bot mails a log to addresses contained in two of the maps. The same timer is used to send the output buffer to the server (such a buffer is needed because if you send too much data at once, the server closes the connection as a security precaution). There is also a mechanism that automatically re- connects the bot if it is disconnected. Now the problem. If the bot disconnects a few times, the log gets mailed normally the first time, but the next time it should be sent, all the containters are empty! This of course means the log can't be sent, 'cause it gets the mail addresses from two of the containers. I have no idea how or why this happens. I'd appreciate any ideas on how to fix this. Here are some parts of the code: typedef std::map guideMap; typedef std::map adrMap; typedef std::set headSet; class GuideBot :public CNBot { private: int assistsAsked; int unansweredAssists; int guestAssists; guideMap theGuides; guideMap theAdmins; headSet theTDHeads; adrMap theAAdr; adrMap theGAdr; void handleLevel1Block(); void processTell(AnsiString tellFrom, AnsiString theTell, UINT type); void findGAlias(AnsiString tellFrom, AnsiString theTell); void findTDAlias(AnsiString tellFrom, AnsiString theTell); void findAAlias(AnsiString tellFrom, AnsiString theTell); void loadAll(); bool isHead(AnsiString user); bool isGHead(AnsiString user); bool isAHead(AnsiString user); bool isTDHead(AnsiString user); public: GuideBot():CNBot() {} GuideBot(AnsiString asHandle, AnsiString asPassword):CNBot(asHandle, asPassword) {} GuideBot(AnsiString asFileName, TClientSocket *tcsConnection):CNBot (asFileName, tcsConnection) {} GuideBot(AnsiString asFileName, TClientSocket *tcsConnection, AnsiString asSection):CNBot(asFileName, tcsConnection, asSection) {} ~GuideBot() {} void onConnect(TCustomWinSocket *Socket); void saveAll(); void mailDump(); int countingSince; }; void __fastcall TForm1::ClientSocketConnect(TObject *Sender, TCustomWinSocket *Socket) { Bot->onConnect(Socket); HandleEdit->Enabled = false; PasswordEdit->Enabled = false; CommandEdit->Enabled = true; if(Application->ShowMainForm) CommandEdit->SetFocus(); TrayMessage(NIM_MODIFY); } void __fastcall TForm1::ClientSocketDisconnect(TObject *Sender, TCustomWinSocket *Socket) { Output->Lines->Add("**** DISCONNECTED ****"); HandleEdit->Enabled = true; PasswordEdit->Enabled = true; CommandEdit->Enabled = false; Bot->saveAll(); if(Bot->stayConnected) { reconnectValue = 4000; reconnectTimer = 0; } TrayMessage(NIM_MODIFY); } void __fastcall TForm1::ClientSocketError(TObject *Sender, TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode) { Bot->saveAll(); ErrorCode = 0; ClientSocket->Close(); reconnectValue = 4000; reconnectTimer = 0; TrayMessage(NIM_MODIFY); } void __fastcall TForm1::SendTimer(TObject *Sender) { reconnectTimer++; if(reconnectTimer == reconnectValue) { reconnectValue = -1; Connect1Click(Sender); } myCounter++; if(Bot != NULL) { Bot->sendoBuffer(ClientSocket->Socket); } if(myCounter%120000 == 0) // every hour { Bot->saveAll(); Output->Clear(); } // if(myCounter == 20160000) // every 7 days if(myCounter == 2000) { Bot->mailDump(); myCounter = 0; Bot->countingSince = myCounter; Bot->saveAll(); } } void GuideBot::onConnect(TCustomWinSocket *Socket) { stayConnected = true; AnsiString command; command = setDGLevel(); Socket->SendText(command + char(10)); Socket->SendText(getHandle() + char(10)); Socket->SendText(getPassword() + char(10)); if(theGuides.begin() == theGuides.end()) int lalala = 0; loadAll(); if(theGuides.begin() == theGuides.end()) int lalala = 0; countingSince = Form1->myCounter; } void GuideBot::loadAll() { int iPos, answered; AnsiString theLine, guideName; TStringList *strList = new TStringList; // declare the list try // use the list in a try block { strList->LoadFromFile("guides.ini"); for(int i = 0; i < strList->Count; i++) { theLine = strList->Strings[i]; iPos = theLine.Pos("\'"); guideName = theLine.SubString(1, iPos-1); theLine = theLine.SubString(iPos+1, theLine.Length()-iPos+1); answered = theLine.SubString(1, theLine.Length()).ToInt(); theGuides.insert(guideMap::value_type(guideName, answered)); } strList->LoadFromFile("admins.ini"); for(int i = 0; i < strList->Count; i++) { theLine = strList->Strings[i]; iPos = theLine.Pos("\'"); guideName = theLine.SubString(1, iPos-1); theLine = theLine.SubString(iPos+1, theLine.Length()-iPos+1); answered = theLine.SubString(1, theLine.Length()).ToInt(); theAdmins.insert(guideMap::value_type(guideName, answered)); } strList->LoadFromFile("gheads.ini"); for(int i = 0; i < strList->Count; i++) { theLine = strList->Strings[i]; iPos = theLine.Pos("\'"); guideName = theLine.SubString(1, iPos-1); theLine = theLine.SubString(iPos+1, theLine.Length()-iPos+1); theGAdr.insert(adrMap::value_type(guideName, theLine)); } strList->LoadFromFile("aheads.ini"); for(int i = 0; i < strList->Count; i++) { theLine = strList->Strings[i]; iPos = theLine.Pos("\'"); guideName = theLine.SubString(1, iPos-1); theLine = theLine.SubString(iPos+1, theLine.Length()-iPos+1); theAAdr.insert(adrMap::value_type(guideName, theLine)); } strList->LoadFromFile("tdheads.ini"); for(int i = 0; i < strList->Count; i++) theTDHeads.insert(strList->Strings[i]); } __finally { delete strList; // destroy the list object } TIniFile *times; times = new TIniFile(ExtractFilePath(Application->ExeName) +"times.ini"); assistsAsked = times->ReadInteger("assists", "assistsAsked", 0); guestAssists = times->ReadInteger("assists", "guestAssists", 0); unansweredAssists = times->ReadInteger("assists", "unansweredAssists", 0); delete times; } void GuideBot::saveAll() { AnsiString aLine; int sec = 60*(Form1->myCounter - countingSince)/2000; int min = 0; int hour = 0; int day = 0; while(sec >= 60) { min = sec/60; sec -= min*60; } while(min >= 60) { hour = min/60; min -= hour*60; } while(hour >= 24) { day = hour/24; hour -= day*24; } TIniFile *times; times = new TIniFile(ExtractFilePath(Application->ExeName) +"times.ini"); times->WriteInteger("guides", "sec", sec); times->WriteInteger("guides", "min", min); times->WriteInteger("guides", "hour", hour); times->WriteInteger("guides", "day", day); times->WriteInteger("assists", "assistsAsked", assistsAsked); times->WriteInteger("assists", "guestAssists", guestAssists); times->WriteInteger("assists", "unansweredAssists", unansweredAssists); delete times; times = new TIniFile(ExtractFilePath(Application->ExeName) +"settings.ini"); times->WriteInteg 18d6 er("Program", "myCounter", Form1->myCounter); delete times; TStringList *strList = new TStringList; // declare the list try // use the list in a try block { guideMap::iterator itr; for(itr = theGuides.begin(); itr != theGuides.end(); itr++) { aLine.sprintf("%s'%i", (*itr).first, (*itr).second); strList->Add(aLine); } // if(strList->Count > 0) strList->SaveToFile("guides.ini"); } __finally { delete strList; // destroy the list object } strList = new TStringList; try // use the list in a try block { guideMap::iterator itr; for(itr = theAdmins.begin(); itr != theAdmins.end(); itr++) { aLine.sprintf("%s'%i", (*itr).first, (*itr).second); strList->Add(aLine); } strList->SaveToFile("admins.ini"); } __finally { delete strList; // destroy the list object } strList = new TStringList; try // use the list in a try block { adrMap::iterator itr; for(itr = theGAdr.begin(); itr != theGAdr.end(); itr++) { aLine.sprintf("%s'%s", (*itr).first, (*itr).second); strList->Add(aLine); } // if(strList->Count > 0) strList->SaveToFile("gheads.ini"); } __finally { delete strList; // destroy the list object } strList = new TStringList; try // use the list in a try block { adrMap::iterator itr; for(itr = theAAdr.begin(); itr != theAAdr.end(); itr++) { aLine.sprintf("%s'%s", (*itr).first, (*itr).second); strList->Add(aLine); } // if(strList->Count > 0) strList->SaveToFile("aheads.ini"); } __finally { delete strList; // destroy the list object } strList = new TStringList; try // use the list in a try block { headSet::iterator itr; for(itr = theTDHeads.begin(); itr != theTDHeads.end(); itr++) strList->Add(*itr); // if(strList->Count > 0) strList->SaveToFile("tdheads.ini"); } __finally { delete strList; // destroy the list object } } void GuideBot::mailDump() { if(theGuides.begin() == theGuides.end()) { loadAll(); return; } TIniFile *times; int total = 0; int guides = 0; int sec; AnsiString ending1, ending2, aLine; guideMap::iterator itr1; adrMap::iterator itr2; TStringList *strList; Form1->MailSender->PostMessageA->Body->Clear(); Form1->MailSender->PostMessageA->ToAddress->Clear(); sec = 60*(Form1->myCounter - countingSince)/2000; int min = 0; int hour = 0; int day = 0; times = new TIniFile(ExtractFilePath(Application->ExeName) +"times.ini"); sec += times->ReadInteger("guides", "sec", 0); min += times->ReadInteger("guides", "min", 0); hour += times->ReadInteger("guides", "hour", 0); day += times->ReadInteger("guides", "day", 0); delete times; while(sec >= 60) { min = sec/60; sec -= min*60; } while(min >= 60) { hour = min/60; min -= hour*60; } while(hour >= 24) { day = hour/24; hour -= day*24; } ending1.sprintf("Counting since %i days, %i hours, %i minutes and %i seconds.", day, hour, min, sec); ending2.sprintf("%i assists were asked, of which %i (%2.1f%%) were guest assists. %i assists were left unanswered (%2.1f%%)", assistsAsked, guestAssists, ((assistsAsked == 0) ? 0.0 : ((float)guestAssists/(float) assistsAsked)*100), unansweredAssists, ((assistsAsked == 0) ? 0.0 : ((float)unansweredAssists/(float)assistsAsked)*100)); strList = new TStringList(); try { for(itr1 = theGuides.begin(); itr1 != theGuides.end(); itr1++) { aLine.sprintf("%s answered %i assists", (*itr1).first, (*itr1).second); Form1->MailSender->PostMessageA->Body->Add(aLine); strList->Add(aLine); guides++; total += (*itr1).second; } aLine.sprintf("%i Guides answered %i assists (%2.1f%% of answered assists)", guides, total, ((assistsAsked-unansweredAssists == 0) ? 0.0 : ((float)total/(float)(assistsAsked-unansweredAssists))*100)); Form1->MailSender->PostMessageA->Body->Add(aLine); strList->Add(aLine); Form1->MailSender->PostMessageA->Body->Add(ending1); strList->Add(ending1); Form1->MailSender->PostMessageA->Body->Add(ending2); strList->Add(ending2); Form1->MailSender->PostMessageA->Subject = "Guide assist stats"; for(itr2 = theGAdr.begin(); itr2 != theGAdr.end(); itr2++) Form1->MailSender->PostMessageA->ToAddress->Add((*itr2).second); Form1->MailSender->Connect(); Form1->MailSender->SendMail(); Form1->MailSender->Disconnect(); Form1->MailSender->PostMessageA->Body->Clear(); Form1->MailSender->PostMessageA->ToAddress->Clear(); guides = 0; total = 0; for(itr1 = theAdmins.begin(); itr1 != theAdmins.end(); itr1++) { aLine.sprintf("%s answered %i assists", (*itr1).first, (*itr1).second); Form1->MailSender->PostMessageA->Body->Add(aLine); strList->Add(aLine); guides++; total += (*itr1).second; } aLine.sprintf("%i Admins answered %i assists (%2.1f%% of answered assists)", guides, total, ((assistsAsked-unansweredAssists == 0) ? 0.0 : ((float)total/(float)(assistsAsked-unansweredAssists))*100)); Form1->MailSender->PostMessageA->Body->Add(aLine); strList->Add(aLine); Form1->MailSender->PostMessageA->Body->Add(ending1); strList->Add(ending1); Form1->MailSender->PostMessageA->Body->Add(ending2); strList->Add(ending2); Form1->MailSender->PostMessageA->Subject = "Admin assist stats"; for(itr2 = theAAdr.begin(); itr2 != theAAdr.end(); itr2++) Form1->MailSender->PostMessageA->ToAddress->Add((*itr2).second); Form1->MailSender->Connect(); Form1->MailSender->SendMail(); Form1->MailSender->Disconnect(); strList->SaveToFile("dump.txt"); } __finally { delete strList; } guideMap::iterator itr; for(itr = theGuides.begin(); itr != theGuides.end(); itr++) (*itr).second = 0; theAdmins.clear(); assistsAsked = 0; guestAssists = 0; unansweredAssists = 0; } . 0