From c5ebec0d1fcb182688de33d76d9c870c6ea9b5d1 Mon Sep 17 00:00:00 2001 From: Vadim Markovtsev Date: Tue, 27 Oct 2015 09:09:42 +0300 Subject: [PATCH] Fix the second crash (dynamic_cast failure) --- client/Client.cpp | 53 +++++++++++++++++++++++----------------------- lib/Connection.cpp | 4 ++-- lib/Connection.h | 39 ++++++++++++++++++++++------------ 3 files changed, 54 insertions(+), 42 deletions(-) diff --git a/client/Client.cpp b/client/Client.cpp index dabe2209f..0471204ae 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -59,8 +59,8 @@ template class CApplyOnCL; class CBaseForCLApply { public: - virtual void applyOnClAfter(CClient *cl, void *pack) const =0; - virtual void applyOnClBefore(CClient *cl, void *pack) const =0; + virtual void applyOnClAfter(CClient *cl, void *pack) const =0; + virtual void applyOnClBefore(CClient *cl, void *pack) const =0; virtual ~CBaseForCLApply(){} template static CBaseForCLApply *getApplier(const U * t=nullptr) @@ -144,7 +144,7 @@ void CClient::waitForMoveAndSend(PlayerColor color) { logNetwork->traceStream() << "Send battle action to server: " << ba; MakeAction temp_action(ba); - sendRequest(&temp_action, color); + sendRequest(&temp_action, color); } return; } @@ -169,8 +169,8 @@ void CClient::run() while(!terminate) { CPack *pack = serv->retreivePack(); //get the package from the server - - if (terminate) + + if (terminate) { vstd::clear_pointer(pack); break; @@ -178,10 +178,10 @@ void CClient::run() handlePack(pack); } - } + } //catch only asio exceptions catch (const boost::system::system_error& e) - { + { logNetwork->errorStream() << "Lost connection to server, ending listening thread!"; logNetwork->errorStream() << e.what(); if(!terminate) //rethrow (-> boom!) only if closing connection was unexpected @@ -313,7 +313,7 @@ void CClient::loadGame(const std::string & fname, const bool server, const std:: *serv << ui8(3) << ui8(loadNumPlayers); //load game; one client if single-player *serv << fname; *serv >> pom8; - if(pom8) + if(pom8) throw std::runtime_error("Server cannot open the savegame!"); else logNetwork->infoStream() << "Server opened savegame properly."; @@ -369,7 +369,7 @@ void CClient::newGame( CConnection *con, StartInfo *si ) { enum {SINGLE, HOST, GUEST} networkMode = SINGLE; - if (con == nullptr) + if (con == nullptr) { CServerHandler sh; serv = sh.connectToServer(); @@ -452,7 +452,7 @@ void CClient::newGame( CConnection *con, StartInfo *si ) logNetwork->infoStream() << boost::format("Player %s will be lead by %s") % color % AiToGive; installNewPlayerInterface(CDynLibHandler::getNewAI(AiToGive), color); } - else + else { installNewPlayerInterface(make_shared(color), color); humanPlayers++; @@ -495,7 +495,7 @@ void CClient::newGame( CConnection *con, StartInfo *si ) // nm->giveActionCB(this); // nm->giveInfoCB(this); // nm->init(); -// +// // erm = nm; //something tells me that there'll at most one module and it'll be ERM // } } @@ -503,7 +503,7 @@ void CClient::newGame( CConnection *con, StartInfo *si ) void CClient::serialize(COSer & h, const int version) { assert(h.saving); - h & hotSeat; + h & hotSeat; { ui8 players = playerint.size(); h & players; @@ -513,7 +513,7 @@ void CClient::serialize(COSer & h, const int version) LOG_TRACE_PARAMS(logGlobal, "Saving player %s interface", i->first); assert(i->first == i->second->playerID); h & i->first & i->second->dllName & i->second->human; - i->second->saveGame(h, version); + i->second->saveGame(h, version); } } } @@ -529,7 +529,7 @@ void CClient::serialize(CISer & h, const int version) for(int i=0; i < players; i++) { std::string dllname; - PlayerColor pid; + PlayerColor pid; bool isHuman = false; h & pid & dllname & isHuman; @@ -541,7 +541,7 @@ void CClient::serialize(CISer & h, const int version) if(pid == PlayerColor::NEUTRAL) { installNewBattleInterface(CDynLibHandler::getNewBattleAI(dllname), pid); - //TODO? consider serialization + //TODO? consider serialization continue; } else @@ -582,7 +582,7 @@ void CClient::serialize(COSer & h, const int version, const std::setfirst); assert(i->first == i->second->playerID); h & i->first & i->second->dllName & i->second->human; - i->second->saveGame(h, version); + i->second->saveGame(h, version); } } } @@ -598,7 +598,7 @@ void CClient::serialize(CISer & h, const int version, const std::setloadGame(h, version); + nInt->loadGame(h, version); } if(playerIDs.count(PlayerColor::NEUTRAL)) @@ -707,7 +707,7 @@ void CClient::battleStarted(const BattleInfo * info) { for(auto &battleCb : battleCallbacks) { - if(vstd::contains_if(info->sides, [&](const SideInBattle& side) {return side.color == battleCb.first; }) + if(vstd::contains_if(info->sides, [&](const SideInBattle& side) {return side.color == battleCb.first; }) || battleCb.first >= PlayerColor::PLAYER_LIMIT) { battleCb.second->setBattle(info); @@ -735,7 +735,7 @@ void CClient::battleStarted(const BattleInfo * info) { boost::unique_lock un(*LOCPLINT->pim); auto bi = new CBattleInterface(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, - Rect((screen->w - 800)/2, + Rect((screen->w - 800)/2, (screen->h - 600)/2, 800, 600), att, def); GH.pushInt(bi); @@ -798,7 +798,7 @@ void CClient::commenceTacticPhaseForInt(shared_ptr battleI catch(...) { handleException(); - } + } } void CClient::invalidatePaths() @@ -822,7 +822,6 @@ const CPathsInfo * CClient::getPathsInfo(const CGHeroInstance *h) int CClient::sendRequest(const CPack *request, PlayerColor player) { static ui32 requestCounter = 0; - ui32 requestID = requestCounter++; logNetwork->traceStream() << boost::format("Sending a request \"%s\". It'll have an ID=%d.") % typeid(*request).name() % requestID; @@ -882,7 +881,7 @@ void CClient::installNewBattleInterface(shared_ptr battleI boost::unique_lock un(*LOCPLINT->pim); PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE); - if(!color) + if(!color) privilagedBattleEventReceivers.push_back(battleInterface); battleints[colorUsed] = battleInterface; @@ -954,7 +953,7 @@ CConnection * CServerHandler::connectToServer() #endif th.update(); //put breakpoint here to attach to server before it does something stupid - + CConnection *ret = justConnectToServer(settings["server"]["server"].String(), port); if(verbose) @@ -1015,8 +1014,8 @@ CConnection * CServerHandler::justConnectToServer(const std::string &host, const try { logNetwork->infoStream() << "Establishing connection..."; - ret = new CConnection( host.size() ? host : settings["server"]["server"].String(), - port.size() ? port : boost::lexical_cast(settings["server"]["port"].Float()), + ret = new CConnection( host.size() ? host : settings["server"]["server"].String(), + port.size() ? port : boost::lexical_cast(settings["server"]["port"].Float()), NAME); } catch(...) diff --git a/lib/Connection.cpp b/lib/Connection.cpp index 0fce3d2c3..1fd56c26f 100644 --- a/lib/Connection.cpp +++ b/lib/Connection.cpp @@ -460,7 +460,7 @@ ui16 CTypeList::getTypeID( const std::type_info *type, bool throws ) const std::vector CTypeList::castSequence(TypeInfoPtr from, TypeInfoPtr to) const { - if(from == to) + if(!strcmp(from->name, to->name)) return std::vector(); // Perform a simple BFS in the class hierarchy. @@ -515,7 +515,7 @@ std::vector CTypeList::castSequence(const std::type_info { //This additional if is needed because getTypeDescriptor might fail if type is not registered // (and if casting is not needed, then registereing should no be required) - if(*from == *to) + if(!strcmp(from->name(), to->name())) return std::vector(); return castSequence(getTypeDescriptor(from), getTypeDescriptor(to)); diff --git a/lib/Connection.h b/lib/Connection.h index b27a77c50..73f9a43e7 100644 --- a/lib/Connection.h +++ b/lib/Connection.h @@ -86,7 +86,7 @@ struct TypeComparer #ifndef __APPLE__ return a->before(*b); #else - return std::string(a->name()) < std::string(b->name()); + return strcmp(a->name(), b->name()) < 0; #endif } }; @@ -106,6 +106,11 @@ struct PointerCaster : IPointerCaster { From * from = (From*)boost::any_cast(ptr); To * ret = dynamic_cast(from); + if (ret == nullptr) + { + // Last resort when RTTI goes mad + ret = static_cast(from); + } return (void*)ret; } @@ -117,6 +122,11 @@ struct PointerCaster : IPointerCaster { auto from = boost::any_cast(ptr); auto ret = std::dynamic_pointer_cast(from); + if (!ret) + { + // Last resort when RTTI goes mad + ret = std::static_pointer_cast(from); + } return ret; } catch(std::exception &e) @@ -173,7 +183,7 @@ private: auto typesSequence = castSequence(fromArg, toArg); boost::any ptr = inputPtr; - for(int i = 0; i < (int)typesSequence.size() - 1; i++) + for(int i = 0; i < static_cast(typesSequence.size()) - 1; i++) { auto &from = typesSequence[i]; auto &to = typesSequence[i + 1]; @@ -182,7 +192,7 @@ private: THROW_FORMAT("Cannot find caster for conversion %s -> %s which is needed to cast %s -> %s", from->name % to->name % fromArg->name() % toArg->name()); auto &caster = casters.at(castingPair); - ptr = (*caster.*CastingFunction)(ptr); //Why does unique_ptr does not have operator->* ..? + ptr = (*caster.*CastingFunction)(ptr); //Why does unique_ptr not have operator->* ..? } return ptr; @@ -225,10 +235,14 @@ public: auto &baseType = typeid(typename std::remove_cv::type); auto derivedType = getTypeInfo(inputPtr); - if(baseType == *derivedType) - return (void*)inputPtr; + if (!strcmp(baseType.name(), derivedType->name())) + { + return const_cast(reinterpret_cast(inputPtr)); + } - return boost::any_cast(castHelper<&IPointerCaster::castRawPtr>((void*)inputPtr, &baseType, derivedType)); + return boost::any_cast(castHelper<&IPointerCaster::castRawPtr>( + const_cast(reinterpret_cast(inputPtr)), &baseType, + derivedType)); } template @@ -237,7 +251,7 @@ public: auto &baseType = typeid(typename std::remove_cv::type); auto derivedType = getTypeInfo(inputPtr.get()); - if(baseType == *derivedType) + if (!strcmp(baseType.name(), derivedType->name())) return inputPtr; return castHelper<&IPointerCaster::castSharedPtr>(inputPtr, &baseType, derivedType); @@ -653,16 +667,15 @@ public: }; template - class CPointerSaver : public CBasicPointerSaver + class CPointerSaver : public CBasicPointerSaver { public: void savePtr(CSaverBase &ar, const void *data) const override - { + { COSer &s = static_cast(ar); - const T *ptr = static_cast(data); - + const T *ptr = static_cast(data); //T is most derived known type, it's time to call actual serialize - const_cast(*ptr).serialize(s,version); + const_cast(ptr)->serialize(s,version); } }; @@ -772,7 +785,7 @@ public: //write type identifier ui16 tid = typeList.getTypeID(data); - *this << tid; + *this << tid; this->savePointerHlp(tid, data); }