I have a strange behaviour on a project that I am doing for my kids. I want to parse an xml with rapidXml and play mp3 with bass on my RasPi1B. Everything works fine if I just press it in one main-function. But as soon as I put the code into another class, my xml-data gets corrupted. I only do c++ in my privat time and work with managed languages, so I am not that into memory-management in c++. So I hope you people can help me (and my kids) out of this issue. Of course I could do everything in just one class, but brain would try to choke me to death ;-)
First of all in a single main function:
// test.cpp
#include <iostream>
#include <rapidxml.hpp>
#include <rapidxml_utils.hpp>
#include <rapidxml_print.hpp>
#include <bass.h>
using namespace std;
using namespace rapidxml;
int main(int argc, char **argv)
{
file<> xmlFile("bin/test.xml");
xml_document<> doc;
doc.parse<0>(xmlFile.data());
print(std::cout, doc, 0); // everything is fine
bool init = BASS_Init(-1, 44100, 0, 0, NULL);
cout << "BASS_Init " << (init ? "true" : "false") << " [error: " << BASS_ErrorGetCode() << "]" << endl;
print(std::cout, doc, 0); // everything is fine
return 0;
}
Then (nearly) the same with a main function and a class/header:
//test2.cpp
#include <iostream>
#include "player.hpp"
using namespace std;
using namespace player;
int main(int argc, char **argv)
{
Player* _pPlayer = new Player();
_pPlayer->loadXml();
_pPlayer->printXml();
_pPlayer->initPlayer();
_pPlayer->printXml();
return 0;
}
// player.cpp
#include "player.hpp"
using namespace std;
using namespace rapidxml;
namespace player {
void Player::loadXml(void)
{
file<> xmlFile("bin/test.xml");
doc.parse<0>(xmlFile.data());
}
void Player::printXml(void)
{
print(std::cout, doc, 0);
}
void Player::initPlayer(void)
{
bool init = BASS_Init(-1, 44100, 0, 0, NULL);
cout << "BASS_Init " << (init ? "true" : "false") << " [error: " << BASS_ErrorGetCode() << "]" << endl;
}
}
// player.hpp
#include <iostream>
#include <rapidxml.hpp>
#include <rapidxml_utils.hpp>
#include <rapidxml_print.hpp>
#include <bass.h>
using namespace std;
using namespace rapidxml;
namespace player {
class Player
{
public:
void loadXml(void);
void printXml(void);
void initPlayer(void);
private:
xml_document<> doc;
};
}
Compiling with:
BASS_PATH = ../libraries/bass_arm
BASS_INCLUDE_PATH = -I$(BASS_PATH)
BASS_LIBRARY_PATH = -L$(BASS_PATH) -L$(BASS_PATH)/hardfp
BASS_LIBS = -lbass -lm
BASS_LINKER_FLAGS = -Wl,-rpath,$(BASS_PATH):$(BASS_PATH)/hardfp
RAPIDXML_PATH = ../libraries/rapidxml-1.13
RAPIDXML_INCLUDE_PATH = -I$(RAPIDXML_PATH)
RAPIDXML_LIBRARY_PATH = -L$(RAPIDXML_PATH)
test:
g++ -std=c++11 src_test/test.cpp -o bin/test $(BASS_INCLUDE_PATH) $(RAPIDXML_INCLUDE_PATH) $(BASS_LIBRARY_PATH) $(RAPIDXML_LIBRARY_PATH) $(BASS_LIBS) $(BASS_LINKER_FLAGS)
test2:
g++ -std=c++11 -g -c src_test/test2.cpp -o src_test/test2.o $(BASS_INCLUDE_PATH) $(RAPIDXML_INCLUDE_PATH)
g++ -std=c++11 -g -c src_test/player.cpp -o src_test/player.o $(BASS_INCLUDE_PATH) $(RAPIDXML_INCLUDE_PATH)
g++ -std=c++11 -g src_test/test2.o src_test/player.o -o bin/test2 $(BASS_LIBRARY_PATH) $(RAPIDXML_LIBRARY_PATH) $(BASS_LIBS) $(BASS_LINKER_FLAGS)
My test.xml looks like this:
<?xml version="1.0" encoding="utf-8"?>
<library>
<series>
<title>Lorem ipsum A</title>
<episode>
<title>dolor sit amet 1</title>
<cover></cover>
<files rfid="x1" current_file="1" timestamp="0">
<file>consetetur/sadipscing_elitr_11.mp3</file>
<file>consetetur/sadipscing_elitr_12.mp3</file>
<file>consetetur/sadipscing_elitr_13.mp3</file>
<file>consetetur/sadipscing_elitr_14.mp3</file>
</files>
</episode>
<episode>
<title>dolor sit amet 2</title>
<cover></cover>
<files rfid="x2" current_file="1" timestamp="0">
<file>consetetur/sadipscing_elitr_21.mp3</file>
<file>consetetur/sadipscing_elitr_22.mp3</file>
<file>consetetur/sadipscing_elitr_23.mp3</file>
<file>consetetur/sadipscing_elitr_24.mp3</file>
</files>
</episode>
</series>
</library>
And here is the output of sudo bin/test
<library>
<series>
<title>Lorem ipsum A</title>
<episode>
<title>dolor sit amet 1</title>
<cover/>
<files rfid="x1" current_file="1" timestamp="0">
<file>consetetur/sadipscing_elitr_11.mp3</file>
<file>consetetur/sadipscing_elitr_12.mp3</file>
<file>consetetur/sadipscing_elitr_13.mp3</file>
<file>consetetur/sadipscing_elitr_14.mp3</file>
</files>
</episode>
<episode>
<title>dolor sit amet 2</title>
<cover/>
<files rfid="x2" current_file="1" timestamp="0">
<file>consetetur/sadipscing_elitr_21.mp3</file>
<file>consetetur/sadipscing_elitr_22.mp3</file>
<file>consetetur/sadipscing_elitr_23.mp3</file>
<file>consetetur/sadipscing_elitr_24.mp3</file>
</files>
</episode>
</series>
</library>
BASS_Init true [error: 0]
<library>
<series>
<title>Lorem ipsum A</title>
<episode>
<title>dolor sit amet 1</title>
<cover/>
<files rfid="x1" current_file="1" timestamp="0">
<file>consetetur/sadipscing_elitr_11.mp3</file>
<file>consetetur/sadipscing_elitr_12.mp3</file>
<file>consetetur/sadipscing_elitr_13.mp3</file>
<file>consetetur/sadipscing_elitr_14.mp3</file>
</files>
</episode>
<episode>
<title>dolor sit amet 2</title>
<cover/>
<files rfid="x2" current_file="1" timestamp="0">
<file>consetetur/sadipscing_elitr_21.mp3</file>
<file>consetetur/sadipscing_elitr_22.mp3</file>
<file>consetetur/sadipscing_elitr_23.mp3</file>
<file>consetetur/sadipscing_elitr_24.mp3</file>
</files>
</episode>
</series>
</library>
And the output of sudo bin/test2:
<library>
<series>
<title>Lorem ipsum A</title>
<episode>
<title>dolor sit amet 1</title>
<cover/>
<files rfid="x1" current_file="1" timestamp="0">
<file>consetetur/sadipscing_elitr_11.mp3</file>
<file>consetetur/sadipscing_elitr_12.mp3</file>
<file>consetetur/sadipscing_elitr_13.mp3</file>
<file>consetetur/sadipscing_elitr_14.mp3</file>
</files>
</episode>
<episode>
<title>dolor sit amet 2</title>
<cover/>
<files rfid="x2" current_file="1" timestamp="0">
<file>consetetur/sadipscing_elitr_21.mp3</file>
<file>consetetur/sadipscing_elitr_22.mp3</file>
<file>consetetur/sadipscing_elitr_23.mp3</file>
<file>consetetur/sadipscing_elitr_24.mp3</file>
</files>
</episode>
</series>
</library>
BASS_Init true [error: 0]
<l1▒B>
CJ>
<>▒CJ▒BJ▒BJ</>
<device>
<de>aults.pcm.device</de>
<`CJ/>
<8CJ BJ="" iec958="1" 1▒CJ="">
<>▒DJ▒BJ6Jcardp3</>
<ults>pcm.cardr/1▒CJ▒CJ</ults>
<▒CJ>devicesg_edefault</▒CJ>
<1>DJPDJ▒CJ(DJ▒CJ</1>
</8CJ>
</device>
<EJpE>
<▒>J▒CJ6J</▒>
<cover/>
<cm.ca did="" J▒DJ="" pEJ="J">
<>devicesdipdefaults.pcm.d</>
<>@EJ▒DJEJ▒DJ</>
<rmat>rawur/sadip1▒EJ▒EJ</rmat>
<▒DJ>6Jtrueltstr_fi</▒DJ>
</cm.ca>
</EJpE>
<CJ>
</l1▒B>
Sorry for the long post! I hope someone can help me. I feel really lost... Thanks in advance!
xmlFile
gets destroyed when Player::loadXml()
goes out of scope. This allows the memory that is occupied by the data of xmlFile
to be assigned to something else (in this case BASE_Init
seems to be writing data to it).
doc
is still using the data that xmlFile
used to be. This leads to undefined behavior.
Please store xmlFile
in the Player
class, like you did with doc
.
Also don't forget to delete
everything you new
, like _pPlayer ;-)