From 15488ddb31f1391f1b271baf047d4a530fc273ff Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Wed, 6 Jul 2011 05:16:25 +0000 Subject: [PATCH] - bugfixes related to attack-boost memory leaks --- source/glest_game/graphics/particle_type.cpp | 13 +- source/glest_game/graphics/renderer.cpp | 12 +- source/glest_game/type_instances/faction.cpp | 6 + source/glest_game/type_instances/faction.h | 1 + source/glest_game/type_instances/unit.cpp | 112 ++++++++++++------ source/glest_game/type_instances/unit.h | 4 +- source/glest_game/world/world.cpp | 58 ++++++--- .../shared_lib/sources/graphics/particle.cpp | 40 +++++-- 8 files changed, 172 insertions(+), 74 deletions(-) diff --git a/source/glest_game/graphics/particle_type.cpp b/source/glest_game/graphics/particle_type.cpp index 0b57fb08..41d96cc1 100644 --- a/source/glest_game/graphics/particle_type.cpp +++ b/source/glest_game/graphics/particle_type.cpp @@ -31,9 +31,14 @@ namespace Glest{ namespace Game{ // ===================================================== // class ParticleSystemType // ===================================================== +const bool checkMemory = false; +static map memoryObjectList; ParticleSystemType::ParticleSystemType() { - //printf("++ Create ParticleSystemType [%p]\n",this); + if(checkMemory) { + printf("++ Create ParticleSystemType [%p]\n",this); + memoryObjectList[this]++; + } teamcolorNoEnergy=false; teamcolorEnergy=false; @@ -47,7 +52,11 @@ ParticleSystemType::ParticleSystemType() { } ParticleSystemType::~ParticleSystemType() { - //printf("-- Delete ParticleSystemType [%p] type = [%s]\n",this,type.c_str()); + if(checkMemory) { + printf("-- Delete ParticleSystemType [%p] type = [%s]\n",this,type.c_str()); + memoryObjectList[this]--; + assert(memoryObjectList[this] == 0); + } } void ParticleSystemType::load(const XmlNode *particleSystemNode, const string &dir, diff --git a/source/glest_game/graphics/renderer.cpp b/source/glest_game/graphics/renderer.cpp index 24680b96..fef0d395 100644 --- a/source/glest_game/graphics/renderer.cpp +++ b/source/glest_game/graphics/renderer.cpp @@ -3144,12 +3144,14 @@ void Renderer::renderSelectionEffects() { for(unsigned int i = 0; i < effect.currentAttackBoostUnits.size(); ++i) { // Remove attack boost upgrades from unit - Unit *affectedUnit = effect.currentAttackBoostUnits[i]; + int findUnitId = effect.currentAttackBoostUnits[i]; + Unit *affectedUnit = game->getWorld()->findUnitById(findUnitId); + if(affectedUnit != NULL) { + Vec3f currVecBoost = affectedUnit->getCurrVectorFlat(); + currVecBoost.y += 0.3f; - Vec3f currVecBoost = affectedUnit->getCurrVectorFlat(); - currVecBoost.y += 0.3f; - - renderSelectionCircle(currVecBoost, affectedUnit->getType()->getSize(), 1.f); + renderSelectionCircle(currVecBoost, affectedUnit->getType()->getSize(), 1.f); + } } } } diff --git a/source/glest_game/type_instances/faction.cpp b/source/glest_game/type_instances/faction.cpp index 0c0639fc..df4e629e 100644 --- a/source/glest_game/type_instances/faction.cpp +++ b/source/glest_game/type_instances/faction.cpp @@ -30,6 +30,10 @@ using Shared::Util::RandomGen; namespace Glest { namespace Game { +CommandGroupSorter::CommandGroupSorter() { + this->unit = NULL; +} + CommandGroupSorter::CommandGroupSorter(Unit *unit) { this->unit = unit; } @@ -82,6 +86,7 @@ bool CommandGroupSorter::operator< (const CommandGroupSorter &j) const { FactionThread::FactionThread(Faction *faction) : BaseThread() { this->faction = faction; + this->unitsInFactionsSorted = NULL; } void FactionThread::setQuitStatus(bool value) { @@ -194,6 +199,7 @@ void FactionThread::execute() { world->getUnitUpdater()->updateUnitCommand(unit,frameIndex.first); } } + //this->unitsInFactionsSorted = NULL; } else { int unitCount = faction->getUnitCount(); diff --git a/source/glest_game/type_instances/faction.h b/source/glest_game/type_instances/faction.h index 4d530aaa..241002a0 100644 --- a/source/glest_game/type_instances/faction.h +++ b/source/glest_game/type_instances/faction.h @@ -53,6 +53,7 @@ class CommandGroupSorter { public: Unit *unit; + CommandGroupSorter(); CommandGroupSorter(Unit *unit); bool operator< (const CommandGroupSorter &j) const; }; diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index ab942ed7..b067a3b1 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -179,7 +179,16 @@ Unit *UnitReference::getUnit() const{ return NULL; } +const bool checkMemory = false; +static map memoryObjectList; + UnitAttackBoostEffect::UnitAttackBoostEffect() { + if(checkMemory) { + printf("++ Create UnitAttackBoostEffect [%p] before count = %d\n",this,memoryObjectList[this]); + memoryObjectList[this]++; + printf("++ Create UnitAttackBoostEffect [%p] after count = %d\n",this,memoryObjectList[this]); + } + boost = NULL; source = NULL; ups = NULL; @@ -187,8 +196,14 @@ UnitAttackBoostEffect::UnitAttackBoostEffect() { } UnitAttackBoostEffect::~UnitAttackBoostEffect() { + if(checkMemory) { + printf("-- Delete UnitAttackBoostEffect [%p] count = %d\n",this,memoryObjectList[this]); + memoryObjectList[this]--; + assert(memoryObjectList[this] == 0); + } + if(ups != NULL) { - //ups->fade(); + ups->fade(); vector particleSystemToRemove; particleSystemToRemove.push_back(ups); @@ -235,6 +250,7 @@ Unit::Unit(int id, UnitPathInterface *unitpath, const Vec2i &pos, const UnitType lastPathfindFailedFrame = 0; lastPathfindFailedPos = Vec2i(0,0); usePathfinderExtendedMaxNodes = false; + this->currentAttackBoostOriginatorEffect.skillType = NULL; RandomGen random; @@ -368,6 +384,8 @@ Unit::~Unit() { while(currentAttackBoostEffects.empty() == false) { //UnitAttackBoostEffect &effect = currentAttackBoostEffects.back(); + UnitAttackBoostEffect *ab = currentAttackBoostEffects.back(); + delete ab; currentAttackBoostEffects.pop_back(); } @@ -747,9 +765,9 @@ void Unit::setVisible(const bool visible) { } for(unsigned int i = 0; i < currentAttackBoostEffects.size(); ++i) { - UnitAttackBoostEffect &effect = currentAttackBoostEffects[i]; - if(effect.ups != NULL) { - effect.ups->setVisible(visible); + UnitAttackBoostEffect *effect = currentAttackBoostEffects[i]; + if(effect != NULL && effect->ups != NULL) { + effect->ups->setVisible(visible); } } if(currentAttackBoostOriginatorEffect.currentAppliedEffect != NULL) { @@ -1139,11 +1157,14 @@ void Unit::undertake() { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] about to undertake unit id = %d [%s] [%s]\n",__FILE__,__FUNCTION__,__LINE__,this->id, this->getFullName().c_str(),this->getDesc().c_str()); // Remove any units that were previously in attack-boost range - if(currentAttackBoostOriginatorEffect.currentAttackBoostUnits.size() > 0) { + if(currentAttackBoostOriginatorEffect.currentAttackBoostUnits.size() > 0 && currentAttackBoostOriginatorEffect.skillType != NULL) { for(unsigned int i = 0; i < currentAttackBoostOriginatorEffect.currentAttackBoostUnits.size(); ++i) { // Remove attack boost upgrades from unit - Unit *affectedUnit = currentAttackBoostOriginatorEffect.currentAttackBoostUnits[i]; - affectedUnit->deapplyAttackBoost(currentAttackBoostOriginatorEffect.skillType->getAttackBoost(), this); + int findUnitId = currentAttackBoostOriginatorEffect.currentAttackBoostUnits[i]; + Unit *affectedUnit = game->getWorld()->findUnitById(findUnitId); + if(affectedUnit != NULL) { + affectedUnit->deapplyAttackBoost(currentAttackBoostOriginatorEffect.skillType->getAttackBoost(), this); + } //printf("!!!! DE-APPLY ATTACK BOOST from unit [%s - %d]\n",affectedUnit->getType()->getName().c_str(),affectedUnit->getId()); } @@ -1351,10 +1372,10 @@ bool Unit::update() { } for(unsigned int i = 0; i < currentAttackBoostEffects.size(); ++i) { - UnitAttackBoostEffect &effect = currentAttackBoostEffects[i]; - if(effect.ups != NULL) { - effect.ups->setPos(getCurrVector()); - effect.ups->setRotation(getRotation()); + UnitAttackBoostEffect *effect = currentAttackBoostEffects[i]; + if(effect != NULL && effect->ups != NULL) { + effect->ups->setPos(getCurrVector()); + effect->ups->setRotation(getRotation()); } } if(currentAttackBoostOriginatorEffect.currentAppliedEffect != NULL) { @@ -1400,11 +1421,15 @@ bool Unit::update() { } // Remove any units that were previously in range - if(currentAttackBoostOriginatorEffect.currentAttackBoostUnits.size() > 0) { + if(currentAttackBoostOriginatorEffect.currentAttackBoostUnits.size() > 0 && currentAttackBoostOriginatorEffect.skillType != NULL) { for(unsigned int i = 0; i < currentAttackBoostOriginatorEffect.currentAttackBoostUnits.size(); ++i) { // Remove attack boost upgrades from unit - Unit *affectedUnit = currentAttackBoostOriginatorEffect.currentAttackBoostUnits[i]; - affectedUnit->deapplyAttackBoost(currentAttackBoostOriginatorEffect.skillType->getAttackBoost(), this); + + int findUnitId = currentAttackBoostOriginatorEffect.currentAttackBoostUnits[i]; + Unit *affectedUnit = game->getWorld()->findUnitById(findUnitId); + if(affectedUnit != NULL) { + affectedUnit->deapplyAttackBoost(currentAttackBoostOriginatorEffect.skillType->getAttackBoost(), this); + } //printf("- #1 DE-APPLY ATTACK BOOST from unit [%s - %d]\n",affectedUnit->getType()->getName().c_str(),affectedUnit->getId()); } @@ -1423,7 +1448,7 @@ bool Unit::update() { Unit *affectedUnit = candidates[i]; if(attackBoost->isAffected(this,affectedUnit) == true) { if(affectedUnit->applyAttackBoost(attackBoost, this) == true) { - currentAttackBoostOriginatorEffect.currentAttackBoostUnits.push_back(affectedUnit); + currentAttackBoostOriginatorEffect.currentAttackBoostUnits.push_back(affectedUnit->getId()); //printf("+ #1 APPLY ATTACK BOOST to unit [%s - %d]\n",affectedUnit->getType()->getName().c_str(),affectedUnit->getId()); } @@ -1461,12 +1486,12 @@ bool Unit::update() { for(unsigned int i = 0; i < candidates.size(); ++i) { Unit *affectedUnit = candidates[i]; - std::vector::iterator iterFound = std::find(currentAttackBoostOriginatorEffect.currentAttackBoostUnits.begin(), currentAttackBoostOriginatorEffect.currentAttackBoostUnits.end(), affectedUnit); + std::vector::iterator iterFound = std::find(currentAttackBoostOriginatorEffect.currentAttackBoostUnits.begin(), currentAttackBoostOriginatorEffect.currentAttackBoostUnits.end(), affectedUnit->getId()); if(attackBoost->isAffected(this,affectedUnit) == true) { if(iterFound == currentAttackBoostOriginatorEffect.currentAttackBoostUnits.end()) { if(affectedUnit->applyAttackBoost(attackBoost, this) == true) { - currentAttackBoostOriginatorEffect.currentAttackBoostUnits.push_back(affectedUnit); + currentAttackBoostOriginatorEffect.currentAttackBoostUnits.push_back(affectedUnit->getId()); //printf("+ #2 APPLY ATTACK BOOST to unit [%s - %d]\n",affectedUnit->getType()->getName().c_str(),affectedUnit->getId()); } @@ -1519,9 +1544,9 @@ bool Unit::update() { bool Unit::unitHasAttackBoost(const AttackBoost *boost, const Unit *source) const { bool result = false; for(unsigned int i = 0; i < currentAttackBoostEffects.size(); ++i) { - const UnitAttackBoostEffect &effect = currentAttackBoostEffects[i]; - if( effect.boost == boost && - effect.source->getType()->getId() == source->getType()->getId()) { + const UnitAttackBoostEffect *effect = currentAttackBoostEffects[i]; + if( effect != NULL && effect->boost == boost && + effect->source->getType()->getId() == source->getType()->getId()) { result = true; break; } @@ -1549,10 +1574,11 @@ bool Unit::applyAttackBoost(const AttackBoost *boost, const Unit *source) { } if(shouldApplyAttackBoost == true) { - currentAttackBoostEffects.push_back(UnitAttackBoostEffect()); - UnitAttackBoostEffect &effect = currentAttackBoostEffects[currentAttackBoostEffects.size()-1]; - effect.boost = boost; - effect.source = source; + //printf("APPLYING ATTACK BOOST START to unit [%s - %d] from unit [%s - %d]\n",this->getType()->getName().c_str(),this->getId(),source->getType()->getName().c_str(),source->getId()); + + UnitAttackBoostEffect *effect = new UnitAttackBoostEffect(); + effect->boost = boost; + effect->source = source; bool wasAlive = alive; int prevMaxHp = totalUpgrade.getMaxHp(); @@ -1567,6 +1593,19 @@ bool Unit::applyAttackBoost(const AttackBoost *boost, const Unit *source) { //printf("#2 wasAlive = %d hp = %d boosthp = %d\n",wasAlive,hp,boost->boostUpgrade.getMaxHp()); + if(showUnitParticles == true) { + effect->upst = new UnitParticleSystemType(); + *effect->upst = *boost->unitParticleSystemTypeForAffectedUnit; + //effect.upst = boost->unitParticleSystemTypeForAffectedUnit; + + effect->ups = new UnitParticleSystem(200); + effect->upst->setValues(effect->ups); + effect->ups->setPos(getCurrVector()); + effect->ups->setFactionColor(getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0)); + Renderer::getInstance().manageParticleSystem(effect->ups, rsGame); + } + currentAttackBoostEffects.push_back(effect); + if(wasAlive == true) { //startDamageParticles startDamageParticles(); @@ -1595,18 +1634,7 @@ bool Unit::applyAttackBoost(const AttackBoost *boost, const Unit *source) { } } - if(showUnitParticles == true) { - effect.upst = new UnitParticleSystemType(); - *effect.upst = *boost->unitParticleSystemTypeForAffectedUnit; - //effect.upst = boost->unitParticleSystemTypeForAffectedUnit; - - effect.ups = new UnitParticleSystem(200); - effect.upst->setValues(effect.ups); - effect.ups->setPos(getCurrVector()); - effect.ups->setFactionColor(getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0)); - Renderer::getInstance().manageParticleSystem(effect.ups, rsGame); - } - //currentAttackBoostEffects.push_back(effect); + //printf("APPLYING ATTACK BOOST END to unit [%s - %d] from unit [%s - %d]\n",this->getType()->getName().c_str(),this->getId(),source->getType()->getName().c_str(),source->getId()); } return shouldApplyAttackBoost; } @@ -1618,7 +1646,7 @@ void Unit::deapplyAttackBoost(const AttackBoost *boost, const Unit *source) { throw runtime_error(szBuf); } - //printf("DE-APPLYING ATTACK BOOST to unit [%s - %d] from unit [%s - %d]\n",this->getType()->getName().c_str(),this->getId(),source->getType()->getName().c_str(),source->getId()); + //printf("DE-APPLYING ATTACK BOOST START to unit [%s - %d] from unit [%s - %d]\n",this->getType()->getName().c_str(),this->getId(),source->getType()->getName().c_str(),source->getId()); bool wasAlive = alive; int prevMaxHp = totalUpgrade.getMaxHp(); @@ -1630,6 +1658,8 @@ void Unit::deapplyAttackBoost(const AttackBoost *boost, const Unit *source) { addItemToVault(&this->hp,this->hp); if(wasAlive == true) { + //printf("DE-APPLYING ATTACK BOOST wasalive = true to unit [%s - %d] from unit [%s - %d]\n",this->getType()->getName().c_str(),this->getId(),source->getType()->getName().c_str(),source->getId()); + //startDamageParticles startDamageParticles(); @@ -1657,14 +1687,18 @@ void Unit::deapplyAttackBoost(const AttackBoost *boost, const Unit *source) { } } + //printf("DE-APPLYING ATTACK BOOST BEFORE END to unit [%s - %d] from unit [%s - %d]\n",this->getType()->getName().c_str(),this->getId(),source->getType()->getName().c_str(),source->getId()); for(unsigned int i = 0; i < currentAttackBoostEffects.size(); ++i) { - UnitAttackBoostEffect &effect = currentAttackBoostEffects[i]; - if(effect.boost == boost && effect.source == source) { + UnitAttackBoostEffect *effect = currentAttackBoostEffects[i]; + if(effect != NULL && effect->boost == boost && effect->source == source) { + delete effect; currentAttackBoostEffects.erase(currentAttackBoostEffects.begin() + i); break; } } + + //printf("DE-APPLYING ATTACK BOOST END to unit [%s - %d] from unit [%s - %d]\n",this->getType()->getName().c_str(),this->getId(),source->getType()->getName().c_str(),source->getId()); } void Unit::tick() { diff --git a/source/glest_game/type_instances/unit.h b/source/glest_game/type_instances/unit.h index 94221d91..64774de8 100644 --- a/source/glest_game/type_instances/unit.h +++ b/source/glest_game/type_instances/unit.h @@ -255,7 +255,7 @@ public: ~UnitAttackBoostEffectOriginator(); const SkillType *skillType; - std::vector currentAttackBoostUnits; + std::vector currentAttackBoostUnits; UnitAttackBoostEffect *currentAppliedEffect; }; @@ -373,7 +373,7 @@ private: UnitAttackBoostEffectOriginator currentAttackBoostOriginatorEffect; - std::vector currentAttackBoostEffects; + std::vector currentAttackBoostEffects; Mutex mutexCommands; diff --git a/source/glest_game/world/world.cpp b/source/glest_game/world/world.cpp index 97b43cf7..0060abaf 100644 --- a/source/glest_game/world/world.cpp +++ b/source/glest_game/world/world.cpp @@ -275,25 +275,29 @@ void World::updateAllFactionUnits() { // Prioritize grouped command units so closest units to target go first // units + const bool sortedUnitsAllowed = true; int factionCount = getFactionCount(); - std::map > unitsInFactionsSorted; - for(int i = 0; i < factionCount; ++i) { - Faction *faction = getFaction(i); - if(faction == NULL) { - throw runtime_error("faction == NULL"); - } - int unitCount = faction->getUnitCount(); - for(int j = 0; j < unitCount; ++j) { - Unit *unit = faction->getUnit(j); - if(unit == NULL) { - throw runtime_error("unit == NULL"); + std::map > unitsInFactionsSorted; + if(sortedUnitsAllowed == true) { + for(int i = 0; i < factionCount; ++i) { + Faction *faction = getFaction(i); + if(faction == NULL) { + throw runtime_error("faction == NULL"); } - unitsInFactionsSorted[faction->getIndex()].push_back(CommandGroupSorter(unit)); + int unitCount = faction->getUnitCount(); + for(int j = 0; j < unitCount; ++j) { + Unit *unit = faction->getUnit(j); + if(unit == NULL) { + throw runtime_error("unit == NULL"); + } + + unitsInFactionsSorted[faction->getIndex()].push_back(CommandGroupSorter(unit)); + } + std::vector &unitListToSort = unitsInFactionsSorted[faction->getIndex()]; + std::sort(unitListToSort.begin(),unitListToSort.end()); } - std::vector &unitListToSort = unitsInFactionsSorted[faction->getIndex()]; - std::sort(unitListToSort.begin(),unitListToSort.end()); } // Signal the faction threads to do any pre-processing @@ -302,8 +306,14 @@ void World::updateAllFactionUnits() { if(faction == NULL) { throw runtime_error("faction == NULL"); } - std::vector &unitListSorted = unitsInFactionsSorted[faction->getIndex()]; - faction->signalWorkerThread(frameCount,&unitListSorted); + + if(sortedUnitsAllowed == true) { + std::vector &unitListSorted = unitsInFactionsSorted[faction->getIndex()]; + faction->signalWorkerThread(frameCount,&unitListSorted); + } + else { + faction->signalWorkerThread(frameCount,NULL); + } } bool workThreadsFinished = false; @@ -340,11 +350,21 @@ void World::updateAllFactionUnits() { throw runtime_error("faction == NULL"); } - std::vector &unitListSorted = unitsInFactionsSorted[faction->getIndex()]; + std::vector *unitListSorted = NULL; + int unitCount = faction->getUnitCount(); + if(sortedUnitsAllowed == true) { + unitListSorted = &unitsInFactionsSorted[faction->getIndex()]; + unitCount = unitListSorted->size(); + } - int unitCount = unitListSorted.size(); for(int j = 0; j < unitCount; ++j) { - Unit *unit = unitListSorted[j].unit; + Unit *unit = NULL; + if(sortedUnitsAllowed == true) { + unit = (*unitListSorted)[j].unit; + } + else { + unit = faction->getUnit(j); + } if(unit == NULL) { throw runtime_error("unit == NULL"); } diff --git a/source/shared_lib/sources/graphics/particle.cpp b/source/shared_lib/sources/graphics/particle.cpp index 13e2de62..720be823 100644 --- a/source/shared_lib/sources/graphics/particle.cpp +++ b/source/shared_lib/sources/graphics/particle.cpp @@ -33,8 +33,14 @@ namespace Graphics { // class ParticleSystem // ===================================================== +const bool checkMemory = false; +static map memoryObjectList; + ParticleSystem::ParticleSystem(int particleCount) { - //printf("++ Create ParticleSystem [%p]\n",this); + if(checkMemory) { + printf("++ Create ParticleSystem [%p]\n",this); + memoryObjectList[this]++; + } //init particle vector blendMode= bmOne; @@ -69,7 +75,11 @@ ParticleSystem::ParticleSystem(int particleCount) { } ParticleSystem::~ParticleSystem(){ - //printf("-- Delete ParticleSystem [%p]\n",this); + if(checkMemory) { + printf("-- Delete ParticleSystem [%p]\n",this); + memoryObjectList[this]--; + assert(memoryObjectList[this] == 0); + } //delete [] particles; particles.clear(); @@ -1084,10 +1094,17 @@ int ParticleManager::findParticleSystems(ParticleSystem *psFind, const vectorparticleSystems); - if(ps != NULL && index >= 0){ + if(ps != NULL && index >= 0) { +// printf("-- Delete cleanupParticleSystems [%p]\n",ps); +// static map deleteList; +// if(deleteList.find(ps) != deleteList.end()) { +// assert(deleteList.find(ps) == deleteList.end()); +// } +// deleteList[ps]++; + delete ps; this->particleSystems.erase(this->particleSystems.begin() + index); } @@ -1095,7 +1112,7 @@ void ParticleManager::cleanupParticleSystems(ParticleSystem *ps){ void ParticleManager::cleanupParticleSystems(vector &particleSystems){ - for(unsigned int i= 0; i < particleSystems.size(); i++){ + for(int i= particleSystems.size()-1; i >= 0; i--){ ParticleSystem *ps= particleSystems[i]; cleanupParticleSystems(ps); } @@ -1106,7 +1123,7 @@ void ParticleManager::cleanupParticleSystems(vector &particleS void ParticleManager::cleanupUnitParticleSystems(vector &particleSystems){ - for(unsigned int i= 0; i < particleSystems.size(); i++){ + for(int i= particleSystems.size()-1; i >= 0; i--){ ParticleSystem *ps= particleSystems[i]; cleanupParticleSystems(ps); } @@ -1120,7 +1137,16 @@ void ParticleManager::manage(ParticleSystem *ps){ void ParticleManager::end(){ while(particleSystems.empty() == false){ - delete particleSystems.back(); + ParticleSystem *ps = particleSystems.back(); + +// printf("-- Delete end() [%p]\n",ps); +// static map deleteList; +// if(deleteList.find(ps) != deleteList.end()) { +// assert(deleteList.find(ps) == deleteList.end()); +// } +// deleteList[ps]++; + + delete ps; particleSystems.pop_back(); } }