Port SpawnGroup stuff to unique_ptr to fix leak

This was leaking on #repop, unsure of other cases, smart pointers should
cover us though.

Direct leak of 3600 byte(s) in 18 object(s) allocated from:
    #0 0x7f2b3dbe0d30 in operator new(unsigned long) (/lib/x86_64-linux-gnu/libasan.so.5+0xead30)
    #1 0x5645dc7c9dff in ZoneDatabase::LoadSpawnGroups(char const*, unsigned short, SpawnGroupList*) ../zone/spawngroup.cpp:241
    #2 0x5645dc9db3f5 in Zone::Depop(bool) ../zone/zone.cpp:1746
    #3 0x5645dca1ba6b in Zone::Repop(unsigned int) ../zone/zone.cpp:1777
    #4 0x5645db4624b7 in command_repop(Client*, Seperator const*) ../zone/command.cpp:5683

Indirect leak of 6552 byte(s) in 273 object(s) allocated from:
    #0 0x7f26f2ff8d30 in operator new(unsigned long) (/lib/x86_64-linux-gnu/libasan.so.5+0xead30)
    #1 0x558d00490bc6 in __gnu_cxx::new_allocator<std::_List_node<SpawnEntry*> >::allocate(unsigned long, void const*) /usr/include/c++/8/ext/new_allocator.h:111
    #2 0x558d00490bc6 in std::allocator_traits<std::allocator<std::_List_node<SpawnEntry*> > >::allocate(std::allocator<std::_List_node<SpawnEntry*> >&, unsigned long) /usr/include/c++/8/bits/alloc_traits.h:436
    #3 0x558d00490bc6 in std::__cxx11::_List_base<SpawnEntry*, std::allocator<SpawnEntry*> >::_M_get_node() /usr/include/c++/8/bits/stl_list.h:450
    #4 0x558d00490bc6 in std::_List_node<SpawnEntry*>* std::__cxx11::list<SpawnEntry*, std::allocator<SpawnEntry*> >::_M_create_node<SpawnEntry* const&>(SpawnEntry* const&) /usr/include/c++/8/bits/stl_list.h:642
    #5 0x558d00490bc6 in void std::__cxx11::list<SpawnEntry*, std::allocator<SpawnEntry*> >::_M_insert<SpawnEntry* const&>(std::_List_iterator<SpawnEntry*>, SpawnEntry* const&) /usr/include/c++/8/bits/stl_list.h:1903
    #6 0x558d00490bc6 in std::__cxx11::list<SpawnEntry*, std::allocator<SpawnEntry*> >::push_back(SpawnEntry* const&) /usr/include/c++/8/bits/stl_list.h:1220
    #7 0x558d00490bc6 in SpawnGroup::AddSpawnEntry(SpawnEntry*) ../zone/spawngroup.cpp:122
    #8 0x558d00490bc6 in ZoneDatabase::LoadSpawnGroups(char const*, unsigned short, SpawnGroupList*) ../zone/spawngroup.cpp:291
    #9 0x558d006a1465 in Zone::Depop(bool) ../zone/zone.cpp:1746
    #10 0x558d006e1adb in Zone::Repop(unsigned int) ../zone/zone.cpp:1777
This commit is contained in:
Michael Cook (mackal) 2021-03-02 12:39:04 -05:00
parent 66f89416d5
commit c6d5864aa9
2 changed files with 19 additions and 40 deletions

View File

@ -78,12 +78,9 @@ uint32 SpawnGroup::GetNPCType(uint16 in_filter)
return (0); return (0);
} }
std::list<SpawnEntry *>::iterator cur, end;
std::list<SpawnEntry *> possible; std::list<SpawnEntry *> possible;
cur = list_.begin(); for (auto &it : list_) {
end = list_.end(); auto se = it.get();
for (; cur != end; ++cur) {
SpawnEntry *se = *cur;
if (!entity_list.LimitCheckType(se->NPCType, se->npc_spawn_limit)) { if (!entity_list.LimitCheckType(se->NPCType, se->npc_spawn_limit)) {
continue; continue;
@ -95,6 +92,7 @@ uint32 SpawnGroup::GetNPCType(uint16 in_filter)
totalchance += se->chance; totalchance += se->chance;
possible.push_back(se); possible.push_back(se);
} }
if (totalchance == 0) { if (totalchance == 0) {
return 0; return 0;
} }
@ -102,10 +100,7 @@ uint32 SpawnGroup::GetNPCType(uint16 in_filter)
int32 roll = 0; int32 roll = 0;
roll = zone->random.Int(0, totalchance - 1); roll = zone->random.Int(0, totalchance - 1);
cur = possible.begin(); for (auto se : possible) {
end = possible.end();
for (; cur != end; ++cur) {
SpawnEntry *se = *cur;
if (roll < se->chance) { if (roll < se->chance) {
npcType = se->NPCType; npcType = se->NPCType;
break; break;
@ -117,42 +112,28 @@ uint32 SpawnGroup::GetNPCType(uint16 in_filter)
return npcType; return npcType;
} }
void SpawnGroup::AddSpawnEntry(SpawnEntry *newEntry) void SpawnGroup::AddSpawnEntry(std::unique_ptr<SpawnEntry> &newEntry)
{ {
list_.push_back(newEntry); list_.push_back(std::move(newEntry));
} }
SpawnGroup::~SpawnGroup() SpawnGroup::~SpawnGroup()
{ {
std::list<SpawnEntry *>::iterator cur, end;
cur = list_.begin();
end = list_.end();
for (; cur != end; ++cur) {
SpawnEntry *tmp = *cur;
safe_delete(tmp);
}
list_.clear(); list_.clear();
} }
SpawnGroupList::~SpawnGroupList() SpawnGroupList::~SpawnGroupList()
{ {
std::map<uint32, SpawnGroup *>::iterator cur, end;
cur = m_spawn_groups.begin();
end = m_spawn_groups.end();
for (; cur != end; ++cur) {
SpawnGroup *tmp = cur->second;
safe_delete(tmp);
}
m_spawn_groups.clear(); m_spawn_groups.clear();
} }
void SpawnGroupList::AddSpawnGroup(SpawnGroup *new_group) void SpawnGroupList::AddSpawnGroup(std::unique_ptr<SpawnGroup> &new_group)
{ {
if (new_group == nullptr) { if (new_group == nullptr) {
return; return;
} }
m_spawn_groups[new_group->id] = new_group; m_spawn_groups[new_group->id] = std::move(new_group);
} }
SpawnGroup *SpawnGroupList::GetSpawnGroup(uint32 in_id) SpawnGroup *SpawnGroupList::GetSpawnGroup(uint32 in_id)
@ -161,7 +142,7 @@ SpawnGroup *SpawnGroupList::GetSpawnGroup(uint32 in_id)
return nullptr; return nullptr;
} }
return (m_spawn_groups[in_id]); return (m_spawn_groups[in_id].get());
} }
bool SpawnGroupList::RemoveSpawnGroup(uint32 in_id) bool SpawnGroupList::RemoveSpawnGroup(uint32 in_id)
@ -224,7 +205,7 @@ bool ZoneDatabase::LoadSpawnGroups(const char *zone_name, uint16 version, SpawnG
} }
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
auto new_spawn_group = new SpawnGroup( auto new_spawn_group = std::make_unique<SpawnGroup>(
atoi(row[0]), atoi(row[0]),
row[1], row[1],
atoi(row[2]), atoi(row[2]),
@ -272,7 +253,7 @@ bool ZoneDatabase::LoadSpawnGroups(const char *zone_name, uint16 version, SpawnG
} }
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
auto new_spawn_entry = new SpawnEntry( auto new_spawn_entry = std::make_unique<SpawnEntry>(
atoi(row[1]), atoi(row[1]),
atoi(row[2]), atoi(row[2]),
atoi(row[3]), atoi(row[3]),
@ -282,7 +263,6 @@ bool ZoneDatabase::LoadSpawnGroups(const char *zone_name, uint16 version, SpawnG
SpawnGroup *spawn_group = spawn_group_list->GetSpawnGroup(atoi(row[0])); SpawnGroup *spawn_group = spawn_group_list->GetSpawnGroup(atoi(row[0]));
if (!spawn_group) { if (!spawn_group) {
safe_delete(new_spawn_entry);
continue; continue;
} }
@ -337,7 +317,7 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawn_group_id, SpawnGroupList *spawn
row[3] row[3]
); );
auto new_spawn_group = new SpawnGroup( auto new_spawn_group = std::make_unique<SpawnGroup>(
atoi(row[0]), atoi(row[0]),
row[1], row[1],
atoi(row[2]), atoi(row[2]),
@ -380,7 +360,7 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawn_group_id, SpawnGroupList *spawn
} }
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
auto new_spawn_entry = new SpawnEntry( auto new_spawn_entry = std::make_unique<SpawnEntry>(
atoi(row[1]), atoi(row[1]),
atoi(row[2]), atoi(row[2]),
atoi(row[3]), atoi(row[3]),
@ -398,7 +378,6 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawn_group_id, SpawnGroupList *spawn
SpawnGroup *spawn_group = spawn_group_list->GetSpawnGroup(atoi(row[0])); SpawnGroup *spawn_group = spawn_group_list->GetSpawnGroup(atoi(row[0]));
if (!spawn_group) { if (!spawn_group) {
safe_delete(new_spawn_entry);
continue; continue;
} }

View File

@ -22,6 +22,7 @@
#include <map> #include <map>
#include <list> #include <list>
#include <memory>
class SpawnEntry { class SpawnEntry {
public: public:
@ -55,7 +56,7 @@ public:
~SpawnGroup(); ~SpawnGroup();
uint32 GetNPCType(uint16 condition_value_filter=1); uint32 GetNPCType(uint16 condition_value_filter=1);
void AddSpawnEntry(SpawnEntry *newEntry); void AddSpawnEntry(std::unique_ptr<SpawnEntry> &newEntry);
uint32 id; uint32 id;
bool wp_spawns; // if true, spawn NPCs at a random waypoint location (if spawnpoint has a grid) instead of the spawnpoint's loc bool wp_spawns; // if true, spawn NPCs at a random waypoint location (if spawnpoint has a grid) instead of the spawnpoint's loc
float roamdist; float roamdist;
@ -66,7 +67,7 @@ public:
uint32 despawn_timer; uint32 despawn_timer;
private: private:
char name_[120]; char name_[120];
std::list<SpawnEntry *> list_; std::list<std::unique_ptr<SpawnEntry>> list_;
uint8 group_spawn_limit; //max # of this entry which can be spawned by this group uint8 group_spawn_limit; //max # of this entry which can be spawned by this group
}; };
@ -75,14 +76,13 @@ public:
SpawnGroupList() {} SpawnGroupList() {}
~SpawnGroupList(); ~SpawnGroupList();
void AddSpawnGroup(SpawnGroup *new_group); void AddSpawnGroup(std::unique_ptr<SpawnGroup> &new_group);
SpawnGroup *GetSpawnGroup(uint32 id); SpawnGroup *GetSpawnGroup(uint32 id);
bool RemoveSpawnGroup(uint32 in_id); bool RemoveSpawnGroup(uint32 in_id);
void ClearSpawnGroups(); void ClearSpawnGroups();
void ReloadSpawnGroups(); void ReloadSpawnGroups();
private: private:
//LinkedList<SpawnGroup*> list_; std::map<uint32, std::unique_ptr<SpawnGroup>> m_spawn_groups;
std::map<uint32, SpawnGroup *> m_spawn_groups;
}; };
#endif #endif