Selaa lähdekoodia

- proper destructors for handlers and lib objects

Ivan Savenko 12 vuotta sitten
vanhempi
sitoutus
4db13ba845

+ 2 - 0
lib/CArtHandler.cpp

@@ -146,6 +146,8 @@ CArtHandler::CArtHandler()
 
 CArtHandler::~CArtHandler()
 {
+	BOOST_FOREACH(CArtifact * art, artifacts)
+		delete art;
 }
 
 std::vector<JsonNode> CArtHandler::loadLegacyData(size_t dataSize)

+ 2 - 0
lib/CCreatureHandler.cpp

@@ -1002,6 +1002,8 @@ int CCreatureHandler::stringToNumber(std::string & s)
 
 CCreatureHandler::~CCreatureHandler()
 {
+	BOOST_FOREACH(auto & creature, creatures)
+		creature.dellNull();
 }
 
 CreatureID CCreatureHandler::pickRandomMonster(const boost::function<int()> &randGen, int tier) const

+ 2 - 2
lib/CCreatureSet.h

@@ -161,7 +161,7 @@ public:
 
 	void addToSlot(SlotID slot, CreatureID cre, TQuantity count, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature
 	void addToSlot(SlotID slot, CStackInstance *stack, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature
-	void clear() OVERRIDE;
+	void clear() override;
 	void setFormation(bool tight);
 	CArmedInstance *castToArmyObj();
 
@@ -177,7 +177,7 @@ public:
 	void eraseStack(SlotID slot); //slot must be occupied
 	void joinStack(SlotID slot, CStackInstance * stack); //adds new stack to the existing stack of the same type
 	void changeStackCount(SlotID slot, TQuantity toAdd); //stack must exist!
-	bool setCreature (SlotID slot, CreatureID type, TQuantity quantity) OVERRIDE; //replaces creature in stack; slots 0 to 6, if quantity=0 erases stack
+	bool setCreature (SlotID slot, CreatureID type, TQuantity quantity) override; //replaces creature in stack; slots 0 to 6, if quantity=0 erases stack
 	void setToArmy(CSimpleArmy &src); //erases all our army and moves stacks from src to us; src MUST NOT be an armed object! WARNING: use it wisely. Or better do not use at all.
 
 	const CStackInstance& getStack(SlotID slot) const; //stack must exist

+ 3 - 0
lib/CGameState.cpp

@@ -763,6 +763,9 @@ CGameState::~CGameState()
 	//delete initialOpts;
 	delete applierGs;
 	delete objCaller;
+
+	BOOST_FOREACH(auto ptr, hpool.heroesPool) // clean hero pool
+		ptr.second.dellNull();
 }
 
 BattleInfo * CGameState::setupBattle(int3 tile, const CArmedInstance *armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance *town)

+ 15 - 0
lib/CObjectHandler.cpp

@@ -255,6 +255,17 @@ CObjectHandler::CObjectHandler()
     logGlobal->traceStream() << "\t\tDone loading banks configs";
 }
 
+CObjectHandler::~CObjectHandler()
+{
+	BOOST_FOREACH(auto & mapEntry, banksInfo)
+	{
+		BOOST_FOREACH(auto & vecEntry, mapEntry.second)
+		{
+			vecEntry.dellNull();
+		}
+	}
+}
+
 int CObjectHandler::bankObjToIndex (const CGObjectInstance * obj)
 {
 	switch (obj->ID) //find appriopriate key
@@ -817,6 +828,8 @@ void CGHeroInstance::initHero()
 		commander->setArmyObj (castToArmyObj()); //TODO: separate function for setting commanders
 		commander->giveStackExp (exp); //after our exp is set
 	}
+	else
+		commander = nullptr;
 
 	hoverName = VLC->generaltexth->allTexts[15];
 	boost::algorithm::replace_first(hoverName,"%s",name);
@@ -904,12 +917,14 @@ void CGHeroInstance::initHeroDefInfo()
 }
 CGHeroInstance::~CGHeroInstance()
 {
+	commander.dellNull();
 }
 
 bool CGHeroInstance::needsLastStack() const
 {
 	return true;
 }
+
 void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
 {
 	if(h == this) return; //exclude potential self-visiting

+ 1 - 0
lib/CObjectHandler.h

@@ -1404,6 +1404,7 @@ public:
 	std::vector<ui32> resVals; //default values of resources in gold
 
 	CObjectHandler();
+	~CObjectHandler();
 
 	int bankObjToIndex (const CGObjectInstance * obj);
 

+ 18 - 3
lib/CSpellHandler.cpp

@@ -131,6 +131,15 @@ CSpell::CSpell()
 	isOffensive = false;
 }
 
+CSpell::~CSpell()
+{
+	for (size_t i=0; i<effects.size(); i++)
+	{
+		for (size_t j=0; j<effects[i].size(); j++)
+			delete effects[i][j];
+	}
+}
+
 std::vector<BattleHex> CSpell::rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool *outDroppedHexes) const
 {
 	std::vector<BattleHex> ret;
@@ -479,7 +488,7 @@ CSpellHandler::CSpellHandler()
 			auto v = v_node.convertTo<std::vector<int> >();
 			auto a = a_node.convertTo<std::vector<int> >();
 
-			for (int i=0; i<4 ; i++)
+			for (int i=0; i<s->effects.size() ; i++)
 			{
 				Bonus * b = JsonUtils::parseBonus(bonus_node);
 				b->sid = s->id; //for all
@@ -493,10 +502,8 @@ CSpellHandler::CSpellHandler()
 
 				s->effects[i].push_back(b);
 			}
-
 		}
 
-
 		auto find_in_map = [](std::string name, std::vector<Bonus::BonusType> &vec)
 		{
 			auto it = bonusNameMap.find(name);
@@ -533,6 +540,14 @@ CSpellHandler::CSpellHandler()
 	}
 }
 
+CSpellHandler::~CSpellHandler()
+{
+	BOOST_FOREACH(auto & spell, spells)
+	{
+		spell.dellNull();
+	}
+}
+
 std::vector<bool> CSpellHandler::getDefaultAllowed() const
 {
 	std::vector<bool> allowedSpells;

+ 3 - 1
lib/CSpellHandler.h

@@ -46,6 +46,7 @@ public:
 	std::vector<SpellID> counteredSpells; //spells that are removed when effect of this spell is placed on creature (for bless-curse, haste-slow, and similar pairs)
 
 	CSpell();
+	~CSpell();
 
 	std::vector<BattleHex> rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool *outDroppedHexes = NULL ) const; //convert range to specific hexes; last optional out parameter is set to true, if spell would cover unavailable hexes (that are not included in ret)
 	si16 mainEffectAnim; //main spell effect animation, in AC format (or -1 when none)
@@ -96,7 +97,7 @@ private:
 
 	ETargetType targetType;
 
-	std::vector<Bonus *> effects [4];
+	std::vector<std::vector<Bonus *> > effects; // [level 0-3][list of effects]
 	std::vector<Bonus::BonusType> immunities; //any of these grants immunity
 	std::vector<Bonus::BonusType> limiters; //all of them are required to be affected
 
@@ -166,6 +167,7 @@ class DLL_LINKAGE CSpellHandler
 
 public:
 	CSpellHandler();
+	~CSpellHandler();
 	std::vector< ConstTransitivePtr<CSpell> > spells;
 
 	/**

+ 9 - 3
lib/CTownHandler.cpp

@@ -73,11 +73,11 @@ CTown::CTown()
 
 CTown::~CTown()
 {
-	BOOST_FOREACH(auto build, buildings)
+	BOOST_FOREACH(auto & build, buildings)
 		build.second.dellNull();
 
-	BOOST_FOREACH(CStructure * str, clientInfo.structures)
-		delete str;
+	BOOST_FOREACH(auto & str, clientInfo.structures)
+		str.dellNull();
 }
 
 CTownHandler::CTownHandler()
@@ -85,6 +85,12 @@ CTownHandler::CTownHandler()
 	VLC->townh = this;
 }
 
+CTownHandler::~CTownHandler()
+{
+	BOOST_FOREACH(auto faction, factions)
+		faction.dellNull();
+}
+
 JsonNode readBuilding(CLegacyConfigParser & parser)
 {
 	JsonNode ret;

+ 1 - 0
lib/CTownHandler.h

@@ -225,6 +225,7 @@ public:
 	std::vector<ConstTransitivePtr<CFaction> > factions;
 
 	CTownHandler(); //c-tor, set pointer in VLC to this
+	~CTownHandler();
 
 	std::vector<JsonNode> loadLegacyData(size_t dataSize) override;
 

+ 6 - 0
lib/filesystem/CResourceLoader.cpp

@@ -193,6 +193,12 @@ CResourceLoader * CResourceHandler::get()
 	}
 }
 
+void CResourceHandler::clear()
+{
+	delete resourceLoader;
+	delete initialLoader;
+}
+
 //void CResourceLoaderFactory::setInstance(CResourceLoader * resourceLoader)
 //{
 //	CResourceLoaderFactory::resourceLoader = resourceLoader;

+ 7 - 0
lib/filesystem/CResourceLoader.h

@@ -375,6 +375,13 @@ public:
 	 */
 	static void initialize();
 
+	/**
+	 * Semi-debug method to track all possible cases of memory leaks
+	 * Used before exiting application
+	 *
+	 */
+	static void clear();
+
 	/**
 	 * Will load all filesystem data from Json data at this path (config/filesystem.json)
 	 * @param prefix - prefix for all paths in filesystem config

+ 10 - 1
server/CVCMIServer.cpp

@@ -30,6 +30,7 @@
 #include "../lib/GameConstants.h"
 #include "../lib/logging/CBasicLogConfigurator.h"
 #include "../lib/CConfigHandler.h"
+#include "../lib/ScopeGuard.h"
 
 #include "../lib/UnlockGuard.h"
 
@@ -315,6 +316,7 @@ CVCMIServer::~CVCMIServer()
 {
 	//delete io;
 	//delete acceptor;
+	/delete firstConnection;
 }
 
 CGameHandler * CVCMIServer::initGhFromHostingConnection(CConnection &c)
@@ -351,8 +353,13 @@ void CVCMIServer::newGame()
 	assert(clients == 1); //multi goes now by newPregame, TODO: custom lobbies
 
 	CGameHandler *gh = initGhFromHostingConnection(c);
+
+	auto onExit = vstd::makeScopeGuard([&]()
+	{
+		vstd::clear_pointer(gh);
+	});
+
 	gh->run(false);
-	vstd::clear_pointer(gh);
 }
 
 void CVCMIServer::newPregame()
@@ -544,6 +551,8 @@ int main(int argc, char** argv)
 		//and return non-zero status so client can detect error
 		throw;
 	}
+	//delete VLC; //can't be re-enabled due to access to already freed memory in bonus system
+	CResourceHandler::clear();
 
   return 0;
 }