From 0a8c58b755c3db07f6dc40bdd1fa48a690c11fce Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 27 Feb 2023 23:55:14 +0000 Subject: [PATCH] Public roads: Fix memory leaks --- src/road.cpp | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/road.cpp b/src/road.cpp index 7a4374e630..3c1926f8e3 100644 --- a/src/road.cpp +++ b/src/road.cpp @@ -32,7 +32,6 @@ #include "map_func.h" #include "core/backup_type.hpp" #include "core/random_func.hpp" -#include "core/arena_alloc.hpp" #include "3rdparty/robin_hood/robin_hood.h" #include @@ -941,13 +940,16 @@ static int32 PublicRoad_CalculateH(AyStar *aystar, AyStarNode *current, OpenList static AyStar PublicRoadAyStar() { - AyStar finder; + AyStar finder {}; finder.CalculateG = PublicRoad_CalculateG; finder.CalculateH = PublicRoad_CalculateH; finder.GetNeighbours = PublicRoad_GetNeighbours; finder.EndNodeCheck = PublicRoad_EndNodeCheck; finder.FoundEndNode = PublicRoad_FoundEndNode; finder.max_search_nodes = 1 << 20; + + finder.Init(1 << _public_road_hash_size); + return finder; } @@ -955,8 +957,6 @@ static bool PublicRoadFindPath(AyStar& finder, const TileIndex from, TileIndex t { finder.user_target = reinterpret_cast(static_cast(to)); - finder.Init(1 << _public_road_hash_size); - AyStarNode start {}; start.tile = from; start.direction = INVALID_TRACKDIR; @@ -981,9 +981,9 @@ struct TownNetwork std::vector towns; }; -void PostProcessNetworks(AyStar &finder, const std::vector &town_networks) +void PostProcessNetworks(AyStar &finder, const std::vector> &town_networks) { - for (auto network : town_networks) { + for (const auto &network : town_networks) { if (network->towns.size() <= 3) { continue; } @@ -1025,13 +1025,9 @@ void GeneratePublicRoads() SetGeneratingWorldProgress(GWP_PUBLIC_ROADS, uint(towns.size() * 2)); - UniformArenaAllocator town_network_storage; - auto new_town_network = [&]() -> TownNetwork * { - return new (town_network_storage.Allocate()) TownNetwork(); - }; // Create a list of networks which also contain a value indicating how many times we failed to connect to them. - std::vector networks; + std::vector> networks; robin_hood::unordered_flat_map town_to_network_map; TileIndex main_town = *std::max_element(towns.begin(), towns.end(), [&](TileIndex a, TileIndex b) { return DistanceFromEdge(a) < DistanceFromEdge(b); }); @@ -1040,11 +1036,13 @@ void GeneratePublicRoads() _public_road_type = GetTownRoadType(Town::GetByTile(main_town)); robin_hood::unordered_flat_set checked_towns; - TownNetwork *main_network = new_town_network(); + std::unique_ptr new_main_network = std::make_unique(); + TownNetwork *main_network = new_main_network.get(); + networks.push_back(std::move(new_main_network)); + main_network->towns.push_back(main_town); main_network->failures_to_connect = 0; - networks.push_back(main_network); town_to_network_map[main_town] = main_network; IncreaseGeneratingWorldProgress(GWP_PUBLIC_ROADS); @@ -1088,7 +1086,7 @@ void GeneratePublicRoads() } if (!found_path) { - std::vector::iterator networks_end; + std::vector>::iterator networks_end; if (networks.size() > 5) { networks_end = networks.begin() + 5; @@ -1096,12 +1094,12 @@ void GeneratePublicRoads() networks_end = networks.end(); } - std::partial_sort(networks.begin(), networks_end, networks.end(), [&](const TownNetwork *a, const TownNetwork *b) { - return town_network_distance(start_town, a) < town_network_distance(start_town, b); + std::partial_sort(networks.begin(), networks_end, networks.end(), [&](const std::unique_ptr &a, const std::unique_ptr &b) { + return town_network_distance(start_town, a.get()) < town_network_distance(start_town, b.get()); }); - auto can_reach = [&](TownNetwork *network) { - if (reachable_from_town != town_to_network_map.end() && network == reachable_from_town->second) { + auto can_reach = [&](const std::unique_ptr &network) { + if (reachable_from_town != town_to_network_map.end() && network.get() == reachable_from_town->second) { return false; } @@ -1122,7 +1120,7 @@ void GeneratePublicRoads() if (network->failures_to_connect > 0) { network->failures_to_connect--; } - town_to_network_map[start_town] = network; + town_to_network_map[start_town] = network.get(); } else { network->failures_to_connect++; } @@ -1130,24 +1128,24 @@ void GeneratePublicRoads() return found_path; }; - std::sort(networks.begin(), networks_end, [&](const TownNetwork *a, const TownNetwork *b) { + std::sort(networks.begin(), networks_end, [&](const std::unique_ptr &a, const std::unique_ptr &b) { return a->failures_to_connect < b->failures_to_connect; }); if (!std::any_of(networks.begin(), networks_end, can_reach)) { // We failed so many networks, we are a separate network. Let future towns try to connect to us. - TownNetwork *new_network = new_town_network(); + std::unique_ptr new_network = std::make_unique(); new_network->towns.push_back(start_town); new_network->failures_to_connect = 0; // We basically failed to connect to this many towns. - int towns_already_in_networks = std::accumulate(networks.begin(), networks.end(), 0, [&](int accumulator, TownNetwork *network) { + int towns_already_in_networks = std::accumulate(networks.begin(), networks.end(), 0, [&](int accumulator, const std::unique_ptr &network) { return accumulator + static_cast(network->towns.size()); }); new_network->failures_to_connect += towns_already_in_networks; - town_to_network_map[start_town] = new_network; - networks.push_back(new_network); + town_to_network_map[start_town] = new_network.get(); + networks.push_back(std::move(new_network)); } } @@ -1155,6 +1153,8 @@ void GeneratePublicRoads() } PostProcessNetworks(finder, networks); + + finder.Free(); } /* ========================================================================= */