rafallauterbach Temat założony przez niniejszego użytkownika |
[C++, SDL2, Rapid XML] bad_alloc » 2019-04-26 12:01:31 Witam, mam problem z kodem. Czasami (zdawać by się mogło losowo) - mój program po prostu nie wczytuje tile_type (czasami nie wczyta ostatniego (~15% na to), a czasami nie wczyta jakichś 2 (jak na razie tylko raz mi się to zdarzyło) ). Teraz dodatkowo dostaję bad_alloc gdy próbuję wczytać mapę. Nie wiem, co jeszcze powiedzieć.. Wrzucę kod, który nie trawi reszty kodu i loga z mojego programu. Czytałem o tym, co to bad_alloc, widziałem kilka tematów dotyczących tego, dowiedziałem się że rapid_xml dziedziczy z memory_pool, ale nadal nie wiem co zepsułem w swoim programie. Wydaje mi się że to może jakiś memory leak, ale wszystko co stworzyłem z new i przechowuję w klasie "Bank" nie powinno mieć tego problemu. Może używam rapidxml a nie prawidłowo / nie usuwam czegoś, z czego nie zdaję sobie sprawy że się w ogóle alokuje... W zasadzie chyba największe zagęszczenie jest w funkcji load_world_xml, bo woła ona load_Tile_type_xml(path,world.bank_tile_type,images) && load_Resource_xml(path,world.bank_resource,images) && load_Settlement_type_xml(path,world.bank_settlement_type,images) && load_Building_xml(path,world.bank_building,images) - czy po zakończeniu każdej z tych "podfunkcji" pamięć użyta tej konkretnej zwalnia się od razu? Chyba nie powinno być problemu związanego z tym. Czytałem też o tym, że rapidxml nie "posiada" std::stringów, które się używa ale nie rozumiem na czym polegał problem w tamtym temacie. Ale wiem, że używam bardzo dużo stringów - każdy bank ma dla każdego elementu string z nazwą. Próbowałem też odpalić program po wyłączeniu przeglądarki (1.5GB ramu więcej) ale efekt był dokładnie ten sam, więc to nie kwestia ilości ramu. Mam też dosyć stary laptop (chyba z 9 lat już będzie miał niedługo) ale naprawdę wątpię, żeby to było coś innego niż kwestia programowa. #include "XML_Parser.h"
#include "rapidxml-1.13/rapidxml.hpp" #include "rapidxml-1.13/rapidxml_utils.hpp" #include <fstream>
#include "World.h" #include <stdint.h>
bool open( rapidxml::xml_document <>& doc, std::string path ) { try { rapidxml::file <> file(( path ).c_str() ); doc.parse < 0 >( file.data() ); } catch( const std::runtime_error & e ) { ERR( "(" << path << ")" << " Runtime error: " << e.what() EL ); return false; } catch( const rapidxml::parse_error & e ) { ERR( "(" << path << ")" << " Parse error: " << e.what() EL ); return false; } catch( const std::exception & e ) { ERR( "(" << path << ")" << " Error: " << e.what() EL ); return false; } catch(...) { ERR( "An unknown error occurred." EL ); return false; } return true; } bool value_string_node( rapidxml::xml_node <> * parent, std::string name, std::string & target, bool silent = false ) { rapidxml::xml_node <> * temp_node = parent->first_node( name.c_str() ); if( temp_node == nullptr ) { if( !silent ) ERR( "Couldn't find " << name << "!" EL ); return false; } else { target = temp_node->value(); return true; } } bool value_long_node( rapidxml::xml_node <> * parent, std::string name, long long & target, bool silent = false ) { std::string v; if( value_string_node( parent, name, v, silent ) ); else return false; target = std::stoll( v ); return true; } int range( long long number, long long vmin, long long vmax, std::string name = "", bool silent = false ) { if( number < vmin ) { if( name != "" ) { if( !silent ) ERR( name << "(" << number << ") must be greater than : " << vmin EL ); } return - 1; } if( number > vmax ) { if( name != "" ) { if( !silent ) ERR( name << "(" << number << ") must be smaller than : " << vmax EL ); } return 1; } return 0; } bool value_int16_node( rapidxml::xml_node <> * parent, std::string name, int16_t & target, bool silent = false ) { long long v; if( value_long_node( parent, name, v, silent ) ); else return false; if( range( v, INT16_MIN, INT16_MAX, name, silent ) ) return false; else { target = v; return true; } } bool value_uint16_node( rapidxml::xml_node <> * parent, std::string name, uint16_t & target, bool silent = false ) { long long v; if( value_long_node( parent, name, v, silent ) ); else return false; if( range( v, 0, UINT16_MAX, name, silent ) ) return false; else { target = v; return true; } } bool value_uint32_node( rapidxml::xml_node <> * parent, std::string name, uint32_t & target, bool silent = false ) { long long v; if( value_long_node( parent, name, v, silent ) ); else return false; if( range( v, 0, UINT32_MAX, name, silent ) ) return false; else { target = v; return true; } }
void XML_Parser::load_Images_xml( std::string path, IBank & bank ) { LOG( "Loading images from file \"" << path + "\"" EL ); rapidxml::xml_document <> doc; if( !open( doc, path ) ) return; rapidxml::xml_node <> * root_node; root_node = doc.first_node( "images" ); for( rapidxml::xml_node <>* img_node = root_node->first_node( "image" ); img_node; img_node = img_node->next_sibling( "image" ) ) { std::string name, img_path; if( value_string_node( img_node, "name", name ) && value_string_node( img_node, "path", img_path ) ) { DEB( "LOADED IMG : " << name EL ); Image * tmp = new Image( bank, name ); tmp->set_path( img_path ); } else { ERR( "failed to load Image!" ); } } } bool XML_Parser::load_Tile_type_xml( std::string path, Bank < Tile_type >& bank, IBank & images ) { path = "xml/tile_type.xml"; LOG( "Loading from file \"" << path + "\"" EL ); rapidxml::xml_document <> doc; if( !open( doc, path ) ) return false; rapidxml::xml_node <> * root_node; root_node = doc.first_node( "tiles" ); for( rapidxml::xml_node <>* tile_node = root_node->first_node( "tile" ); tile_node; tile_node = tile_node->next_sibling( "tile" ) ) { std::string name, img_name; int16_t deffense_bonus; uint16_t id, movement_cost; if( value_string_node( tile_node, "name", name ) && value_string_node( tile_node, "img", img_name ) && value_uint16_node( tile_node, "id", id ) && value_int16_node( tile_node, "defense_bonus", deffense_bonus ) && value_uint16_node( tile_node, "movement_cost", movement_cost ) ) { Image * img = images.get_( img_name ); if( img == nullptr ) { ERR( "Image : \"" << img_name << "\" not found!" EL ); continue; } Tile_type & tile_t = *( new Tile_type( img ) ); tile_t.id = id; tile_t.name = name; tile_t.deffense_bonus = deffense_bonus; tile_t.movement_cost = movement_cost; bank.put_( name, & tile_t ); } else { ERR( "Failed to read xml data for tile type!" EL ); } } return true; } bool XML_Parser::load_Resource_xml( std::string path, RBank & bank, IBank & images ) { path = "xml/resources.xml"; LOG( "Loading from file \"" << path + "\"" EL ); rapidxml::xml_document <> doc; if( !open( doc, path ) ) return false; rapidxml::xml_node <> * root_node, * test_node; root_node = doc.first_node( "resources" ); for( rapidxml::xml_node <>* res_node = root_node->first_node( "resource" ); res_node; res_node = res_node->next_sibling( "resource" ) ) { std::string name, img_name; uint16_t mass; uint32_t value; Image * img; if( value_string_node( res_node, "name", name ) && value_uint32_node( res_node, "value", value ) ) { if( !value_uint16_node( res_node, "mass", mass, true ) ) mass = 1; if( !value_string_node( res_node, "img", img_name, true ) ) img_name = "unknown"; img = images.get_( img_name ); Resource * res; test_node = res_node->first_node( "weapon" ); if( test_node != nullptr ) { Weapon_type * wpn = new Weapon_type( img, name, mass, value ); res = wpn; bank.weapon.put( name, wpn ); } else { test_node = res_node->first_node( "armour" ); if( test_node != nullptr ) { Armour_type * arm = new Armour_type( img, name, mass, value ); res = arm; bank.weapon.put( name, arm ); } else { res = new Resource( img, name, mass, value ); } } bank.put_( name, res ); } else { ERR( "Failed to read xml data for tile type!" EL ); } } return true; } bool XML_Parser::load_Building_xml( std::string path, Bank < Building >& bank, IBank & images ) { path = "xml/buildings.xml"; LOG( "Loading from file \"" << path + "\"" EL ); rapidxml::xml_document <> doc; if( !open( doc, path ) ) return false; return true; } bool XML_Parser::load_Settlement_type_xml( std::string path, Bank < Settlement_type >& bank, IBank & images ) { path = "xml/settlement_type.xml"; LOG( "Loading from file \"" << path + "\"" EL ); rapidxml::xml_document <> doc; if( !open( doc, path ) ) return false; return true; }
bool XML_Parser::load_map_xml( std::string path, World & world ) { LOG( "Loading map from file \"" << path + "map.xml\"" EL ); rapidxml::xml_document <> doc; if( !open( doc, path ) ) return false; bool success = true; rapidxml::xml_node <> * map_node, * temp_node; map_node = doc.first_node( "map" ); { rapidxml::xml_node <>* dim_node = map_node->first_node( "dimentions" ); if( dim_node == nullptr ) { ERR( "Couldn't load map. The map have no dimentions! Aborting map loading" EL ); return false; } else { if( !value_uint16_node( dim_node, "width", world.gMap.mWidth ) ) success = false; if( !value_uint16_node( dim_node, "height", world.gMap.mHeight ) ) success = false; } } { rapidxml::xml_node <>* tile_defines_node = map_node->first_node( "tile_defines" ); if( tile_defines_node == nullptr ) { ERR( "Couldn't load map. No tile defines! Aborting map loading" EL ); return false; } else { } } return true; }
bool XML_Parser::load_world_xml( std::string path, World & world, IBank & images ) { std::cout << std::endl; LOG( "Loading world from path : " << path EL ); if( load_Tile_type_xml( path, world.bank_tile_type, images ) && load_Resource_xml( path, world.bank_resource, images ) && load_Settlement_type_xml( path, world.bank_settlement_type, images ) && load_Building_xml( path, world.bank_building, images ) ); else { ERR( "Failed to load world assets!" EL ); return false; } std::ifstream info( path + "info.inf" ); std::string line; while( info.good() ) { getline( info, line ); if( line.substr( 0, 5 ) == "name:" ) { if( world.name == "" ) { line.erase( 0, 5 ); world.name = line; } else { WAR( "Duplicate parameter \"name:\" world path : " << path EL ); } } else if( line.substr( 0, 4 ) == "map:" ) { if( world.map_loaded == false ) { line.erase( 0, 4 ); if( load_map_xml( path + line, world ) ) { world.map_loaded = true; } else { WAR( "Fail during map load, world path : " << path EL ); } } else { WAR( "Duplicate parameter \"map:\" world path : " << path EL ); } } else if( line.substr( 0, 8 ) == "version:" ) { } else if( line == "" ) { } else { LOG( "unknown world info parameter : " << line EL ); } } info.close(); return true; }
void XML_Parser::save_to_file( World *, std::string ) { return; }
ENTER - skip / non empty + enter - debug
LOG : Loading images from file "xml/images.xml" DEB : LOADED IMG : unknown DEB : LOADED IMG : button DEB : LOADED IMG : main scene DEB : LOADED IMG : game background DEB : LOADED IMG : pressed DEB : LOADED IMG : selected DEB : LOADED IMG : TILE_AMBIENT DEB : LOADED IMG : TILE_OCEAN DEB : LOADED IMG : TILE_GRASSLAND DEB : LOADED IMG : TILE_FOREST LOG : Image "main scene". Does not have texture, trying to reload one... LOG : Image "button". Does not have texture, trying to reload one...
LOG : Loading world from path : save/world_new_world/ LOG : Loading from file "xml/tile_type.xml" WARN ! couldn't find : TILE_DESERT ERROR! Image : "TILE_DESERT" not found! LOG : Loading from file "xml/resources.xml" LOG : Loading from file "xml/settlement_type.xml" LOG : Loading from file "xml/buildings.xml" LOG : Loading map from file "save/world_new_world/map_earth/map.xml" ERROR! (save/world_new_world/map_earth/) Error: std::bad_alloc WARN ! Fail during map load, world path : save/world_new_world/ LOG : Image "game background". Does not have texture, trying to reload one... DEB : Deleting window nr : 0 DEB : Game finished properly...
Process returned 0 (0x0) execution time : 3.740 s Press ENTER to continue.
//log dokładnie tego samego programu odpalonego drugi raz... ENTER - skip / non empty + enter - debug
LOG : Loading images from file "xml/images.xml" DEB : LOADED IMG : unknown DEB : LOADED IMG : button DEB : LOADED IMG : main scene DEB : LOADED IMG : game background DEB : LOADED IMG : pressed DEB : LOADED IMG : selected DEB : LOADED IMG : TILE_AMBIENT DEB : LOADED IMG : TILE_OCEAN DEB : LOADED IMG : TILE_GRASSLAND DEB : LOADED IMG : TILE_FOREST DEB : LOADED IMG : TILE_DESERT LOG : Image "main scene". Does not have texture, trying to reload one... LOG : Image "button". Does not have texture, trying to reload one...
LOG : Loading world from path : save/world_new_world/ LOG : Loading from file "xml/tile_type.xml" LOG : Loading from file "xml/resources.xml" LOG : Loading from file "xml/settlement_type.xml" LOG : Loading from file "xml/buildings.xml" LOG : Loading map from file "save/world_new_world/map_earth/map.xml" ERROR! (save/world_new_world/map_earth/) Error: std::bad_alloc WARN ! Fail during map load, world path : save/world_new_world/ LOG : Image "game background". Does not have texture, trying to reload one... DEB : Deleting window nr : 0 DEB : Game finished properly...
Process returned 0 (0x0) execution time : 3.135 s Press ENTER to continue.
//xml, w czasie wczytywania którego wyskakuje bład. Jest well-formatted według programu XML Copy Editor. Chyba problem nie dotyczy tego pliku...
<?xml version="1.0" encoding="UTF-8"?>
<map> <dimentions> <width>17</width> <height>11</height> </dimentions> <tile_defines> <def> <name>_</name> <tile_type>ocean</tile_type> <elevation>-4</elevation> <!-- <wild_resources>0</wild_resources> not implemented yet--> </def> <def> <name>.</name> <tile_type>grassland</tile_type> <elevation>1</elevation> </def> <def> <name>-</name> <tile_type>desert</tile_type> <elevation>1</elevation> </def> <def> <name>M</name> <tile_type>desert</tile_type> <elevation>3</elevation> <!-- its hill! --> </def> <def> <name>#</name> <tile_type>forest</tile_type> <elevation>1</elevation> </def> </tile_defines>
<tile_placement> ___.#.-----.#.___ __#...-M-M-...#__ _.#.#--M_M--#.#._ _#.#_--___--_#.#_ ##..M_-----_M..## ..#.___-M-___.#.. ##..M_-----_M..## _#.#_--___--_#.#_ _.#.#--M_M--#.#._ __#...-M-M-...#__ ___.#.-----.#.___ </tile_placement>
<player_defines> <player> <name>nature</name> <sign>-</sign> </player> <player> <name>Charlemagne</name> <sign>C</sign> <color> <r>20</r> <g>0</g> <b>168</b> </color> </player> <player> <name>Al-Amin</name> <!-- Muhamed --> <sign>A</sign> <color> <r>32</r> <g>218</g> <b>0</b> </color> </player> <player> <name>Qutlugh</name> <!-- bilge --> <sign>Q</sign> <color> <r>212</r> <g>84</g> <b>0</b> </color> </player> <player> <name>Dezong</name> <sign>D</sign> <color> <r>216</r> <g>192</g> <b>0</b> </color> </player> </player_defines>
<owner_placement> ----------------- --CC---------QQ-- --C-C-------Q-Q-- -C-------------Q- -C-------------Q- ----------------- -A-------------D- -A-------------D- --A-A-------D-D-- --AA---------DD-- ----------------- </owner_placement>
</map>
|