Hi all
I'm using SFML (2.1) for a personal project and i want everything to be as good as possible.
I'm using a class to load all of my ressources (images, fonts, sounds) at the program starts.
This class is a singleton. The problem is not with the class itself, but with the "loadFromFile" method, in the sf::Font class.
Whenever i have a sf::Font attribute in my class, the code randomly crashes.
I already had this issue and I fixed it by doing something a little bit tricky (Here is the old code) :
class Blob
{
private:
sf::Font *_font;
public:
Blob();
virtual ~Blob();
};
// Now the CPP source file
Blob::Blob()
{
_font = new sf::Font();
font->loadFromFile("arial.ttf");
}
Doing this makes the code crash.
Here is the fix :
// Header file
class Blob
{
private:
static sf::Font _font;
public:
// Ctor / Dtor
void init();
};
// CPP Source code
Blob::Blob()
{
}
void Blob::init()
{
_font.loadFromFile("arial.ttf");
}
sf::Font Blob::_font;
Now, about the real problem.
I have a FontLoader class, which is supposed to load all the fonts needed in the whole program.
It contains a std::map<std::string, sf::Font>.
Then when i want a font, i just have to do "FontLoader->getFont("NAME"), what returns the case in the map corresponding to "NAME"
But seeing the problem i show before, this cannot work !
Actually, it doesnt. I'm having a malloc() memory corruption when trying to allcate an object of type sf::Font
See the code here :
(Singleton is just a way to make my class global, available for all the other class)
class SFFontLoader : public Singleton<SFFontLoader>
{
friend class Singleton<SFFontLoader>;
private:
std::map<std::string, sf::Font *> _fontMap;
public:
void loadFont(std::string const &path, std::string const &name);
sf::Font &getFont(std::string const &name) {return *_fontMap[name];};
private:
SFFontLoader();
virtual ~SFFontLoader();
};
And the CPP file
#include "SFFontLoader.hh"
SFFontLoader::SFFontLoader()
{
}
SFFontLoader::~SFFontLoader()
{
}
void SFFontLoader::loadFont(std::string const &path,
std::string const &name)
{
_fontMap[name] = new sf::Font;
if (!(_fontMap[name]->loadFromFile(path)))
std::cerr << "Error : failed to load font \"" << path << "\"" << std::endl;
}
And valgrind's console :
==5936== Invalid write of size 8
==5936== at 0x5266038: std::vector<unsigned char, std::allocator<unsigned char> >::_M_fill_insert(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned long, unsigned char const&) (in /usr/lib/libsfml-graphics.so.2.1)
==5936== by 0x5264D75: sf::Font::loadGlyph(unsigned int, unsigned int, bool) const (in /usr/lib/libsfml-graphics.so.2.1)
==5936== by 0x526540D: sf::Font::getGlyph(unsigned int, unsigned int, bool) const (in /usr/lib/libsfml-graphics.so.2.1)
==5936== by 0x5285BE9: sf::Text::updateGeometry() (in /usr/lib/libsfml-graphics.so.2.1)
==5936== by 0x40C079: SFLabel::setText(std::string const&) (SFLabel.cpp:25)
==5936== by 0x403100: main (main.cpp:52)
==5936== Address 0xce07828 is 0 bytes after a block of size 104 alloc'd
==5936== at 0x4C2C7A7: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5936== by 0x40BAA8: SFFontLoader::loadFont(std::string const&, std::string const&) (SFFontLoader.cpp:24)
==5936== by 0x40B6DE: SFRessourcesManager::loadDefaultRessources() (SFRessourcesManager.cpp:30)
==5936== by 0x402DAD: main (main.cpp:27)
(Have fun reading this, the only usefull thing is at the top)
I have a solution to make this work :
Instead of map<string, sf::Font *>, juste do map<strring, sf::Font> then remove the new sf::Font line.
This works, the font appears, not memory corruption, but valgrinds yeld me some strange things (i think it tells me there's a problem when accessing to the _fontMap[name], well i actually have no idea why)
So, can anyone tell me why i cannot allocate an object of type sf::Font ?
Sorry, the post is a bit long but i wanted to be as accurate as possible.
Thanks for your help.