So I'm trying to create a small resource managing class where I simply map filepaths to textures/fonts. But when I started testing my resource manager by loading fonts into sf::Text objects things started crashing, a lot. So before I write too much text I'll just give you a minimal example of what works and what does not.
sf::RenderWindow m_window(sf::VideoMode(800, 600), "Test");
std::unique_ptr<sf::Font> font = std::unique_ptr<sf::Font>(new sf::Font());
if(!font->loadFromFile("a_font.ttf")) // This line causes a crash, see below for output
std::cout << "ERROR" << std::endl;
sf::Text text;
text.setFont(*font);
text.setString("Test");
text.setCharacterSize(24);
text.setColor(sf::Color::Red);
while (m_window.isOpen())
{
sf::Event event;
while (m_window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
m_window.close();
}
m_window.clear();
m_window.draw(text);
m_window.display();
}
Which gives the error
*** Error in `/gameBinaryDirectoryPathIsHere/': malloc(): memory corruption: 0x000000000062a470 ***
And a GDB backtrace
#0 0x00007ffff6ec8bb9 in __GI_raise (sig=sig@entry=6)
at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1 0x00007ffff6ecbfc8 in __GI_abort () at abort.c:89
#2 0x00007ffff6f05e14 in __libc_message (do_abort=1,
fmt=fmt@entry=0x7ffff7014668 "*** Error in `%s': %s: 0x%s ***\n")
at ../sysdeps/posix/libc_fatal.c:175
#3 0x00007ffff6f139b6 in malloc_printerr (ptr=0x62a470,
str=0x7ffff70107da "malloc(): memory corruption", action=<optimized out>)
at malloc.c:4996
#4 _int_malloc (av=0x7ffff7251760 <main_arena>, bytes=392) at malloc.c:3447
#5 0x00007ffff6f15230 in __GI___libc_malloc (bytes=392) at malloc.c:2891
#6 0x00007ffff6643aa0 in ft_mem_qalloc ()
from /usr/lib/x86_64-linux-gnu/libfreetype.so.6
#7 0x00007ffff6643ae8 in ft_mem_alloc () from /usr/lib/x86_64-linux-gnu/libfreetype.so.6
#8 0x00007ffff664482e in FT_New_Library ()
from /usr/lib/x86_64-linux-gnu/libfreetype.so.6
#9 0x00007ffff663f5c4 in FT_Init_FreeType ()
from /usr/lib/x86_64-linux-gnu/libfreetype.so.6
#10 0x00007ffff7ba727f in sf::Font::loadFromFile(std::string const&) ()
In my real code I use a std::unordered_map<std::string, std::unique_ptr<sf::Font> > but the results here are the same. So then you might think "Why not put the resources on the stack, since STL map's doesn't invalidate its elements", and then we get this:
std::unordered_map<std::string, sf::Font> fontMap;
sf::Font font;
if(!font.loadFromFile("assets/a_font.ttf"))
std::cout << "ERROR" << std::endl;
fontMap["assets/a_font.ttf"] = font;
sf::Text text;
text.setFont(fontMap["assets/a_font.ttf"]);
text.setString("Test");
text.setCharacterSize(24);
text.setColor(sf::Color::Red);
while (m_window.isOpen())
{
sf::Event event;
while (m_window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
m_window.close();
}
m_window.clear();
m_window.draw(text);
m_window.display();
}
Which appears to run "fine", window opens and stays open, yet there's no text displaying. And when I close the window I get a segfault which doesn't say much (in gdb) other than pointing to the destruction of the std::unordered_map. Although in this case I'd rather have my resources on the heap since (in my opinion) it makes management/usage of them easier.
Finally, the below example works just fine to have some sort of reference:
sf::Font font;
if(!font.loadFromFile("assets/a_font.ttf"))
std::cout << "ERROR" << std::endl;
sf::Text text;
text.setFont(font);
text.setString("Test");
text.setCharacterSize(24);
text.setColor(sf::Color::Red);
while (m_window.isOpen())
{
sf::Event event;
while (m_window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
m_window.close();
}
m_window.clear();
m_window.draw(text);
m_window.display();
}