1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-02 00:10:22 +02:00

Merge pull request #129 from vmarkovtsev/issue/2306

Fix the second crash (dynamic_cast failure)
This commit is contained in:
Alexander Shishkin 2015-10-27 13:23:42 +03:00
commit 610318d5d3
3 changed files with 54 additions and 42 deletions

View File

@ -59,8 +59,8 @@ template <typename T> 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<typename U> 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<CPlayerInterface>(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::set<PlayerColor
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);
}
}
}
@ -598,7 +598,7 @@ void CClient::serialize(CISer & h, const int version, const std::set<PlayerColor
for(int i=0; i < players; i++)
{
std::string dllname;
PlayerColor pid;
PlayerColor pid;
bool isHuman = false;
h & pid & dllname & isHuman;
@ -611,7 +611,7 @@ void CClient::serialize(CISer & h, const int version, const std::set<PlayerColor
{
if(playerIDs.count(pid))
installNewBattleInterface(CDynLibHandler::getNewBattleAI(dllname), pid);
//TODO? consider serialization
//TODO? consider serialization
continue;
}
else
@ -633,7 +633,7 @@ void CClient::serialize(CISer & h, const int version, const std::set<PlayerColor
if(playerIDs.count(pid))
installNewPlayerInterface(nInt, pid);
nInt->loadGame(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<boost::recursive_mutex> 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<CBattleGameInterface> 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<CBattleGameInterface> battleI
boost::unique_lock<boost::recursive_mutex> 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<std::string>(settings["server"]["port"].Float()),
ret = new CConnection( host.size() ? host : settings["server"]["server"].String(),
port.size() ? port : boost::lexical_cast<std::string>(settings["server"]["port"].Float()),
NAME);
}
catch(...)

View File

@ -460,7 +460,7 @@ ui16 CTypeList::getTypeID( const std::type_info *type, bool throws ) const
std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(TypeInfoPtr from, TypeInfoPtr to) const
{
if(from == to)
if(!strcmp(from->name, to->name))
return std::vector<CTypeList::TypeInfoPtr>();
// Perform a simple BFS in the class hierarchy.
@ -515,7 +515,7 @@ std::vector<CTypeList::TypeInfoPtr> 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<CTypeList::TypeInfoPtr>();
return castSequence(getTypeDescriptor(from), getTypeDescriptor(to));

View File

@ -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<void*>(ptr);
To * ret = dynamic_cast<To*>(from);
if (ret == nullptr)
{
// Last resort when RTTI goes mad
ret = static_cast<To*>(from);
}
return (void*)ret;
}
@ -117,6 +122,11 @@ struct PointerCaster : IPointerCaster
{
auto from = boost::any_cast<SmartPt>(ptr);
auto ret = std::dynamic_pointer_cast<To>(from);
if (!ret)
{
// Last resort when RTTI goes mad
ret = std::static_pointer_cast<To>(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<int>(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<TInput>::type);
auto derivedType = getTypeInfo(inputPtr);
if(baseType == *derivedType)
return (void*)inputPtr;
if (!strcmp(baseType.name(), derivedType->name()))
{
return const_cast<void*>(reinterpret_cast<const void*>(inputPtr));
}
return boost::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>((void*)inputPtr, &baseType, derivedType));
return boost::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>(
const_cast<void*>(reinterpret_cast<const void*>(inputPtr)), &baseType,
derivedType));
}
template<typename TInput>
@ -237,7 +251,7 @@ public:
auto &baseType = typeid(typename std::remove_cv<TInput>::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 <typename T>
class CPointerSaver : public CBasicPointerSaver
class CPointerSaver : public CBasicPointerSaver
{
public:
void savePtr(CSaverBase &ar, const void *data) const override
{
{
COSer &s = static_cast<COSer&>(ar);
const T *ptr = static_cast<const T*>(data);
const T *ptr = static_cast<const T*>(data);
//T is most derived known type, it's time to call actual serialize
const_cast<T&>(*ptr).serialize(s,version);
const_cast<T*>(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);
}