Exception 0x00000004 (sfml-graphics-2.dll) occuring after compilation

0

Recently, I've started to learn SFML. The first thing I wanted to do was a simple menu - so I've created an interface for all menus, containing everything necessary for other menus in protected field. However, my code throws an exception at some point, and I have no idea, why.

#include <SFML/Graphics.hpp>
#include <iostream>

class Menu
{
protected:
    sf::Color red;
    sf::Color white;
    std::vector<sf::Text> displayedText;
    int currentOption{ 0 };
public:
    virtual void draww(sf::RenderWindow& window) = 0;
    virtual void clickButton() = 0;
    virtual void moveUp() = 0;
    virtual void moveDown() = 0;
};

class FirstMenu : public Menu
{
public:
    FirstMenu(sf::RenderWindow& window)
    {
        sf::Text text;
        sf::Font font;
        if (!font.loadFromFile("arial.ttf"))
        {
            std::cout << "Font error. \n";
        }
        text.setFont(font);
        text.setString("Play");
        displayedText.push_back(text);
        text.setString("Options");
        displayedText.push_back(text);
        displayedText[0].setFillColor(red);
        displayedText[0].setPosition(20, 30);
        displayedText[1].setPosition(30, 30);
    }
    virtual void clickButton()
    {
        switch (currentOption)
        {
        case 0:
            std::cout << "Playing. \n";
            break;
        case 1:
            std::cout << "Options. \n";
            break;
        }
    }
    virtual void moveUp()
    {
        currentOption++;
        displayedText[currentOption].setFillColor(white);
        for (int i = 0; i < displayedText.size(); i++)
        {
            if (i == currentOption)
            {
                displayedText[i].setFillColor(red);
            }
        }
    }
    virtual void moveDown()
    {
        currentOption--;
        displayedText[currentOption].setFillColor(white);
        for (int i = 0; i < displayedText.size(); i++)
        {
            if (i == currentOption)
            {
                displayedText[i].setFillColor(red);
            }
        }
    }
    virtual void draww(sf::RenderWindow& window)
    {
        if (!displayedText.empty())
        {
            for (int i = 0; i < displayedText.size(); i++)
            {
                window.draw(displayedText[i]); //Exception thrown here
            }
        }
    }
};

int main()
{
    sf::RenderWindow window(sf::VideoMode(500, 500), "SFML works!");
    FirstMenu menu(window);
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }
        window.clear();
        menu.draww(window);
        window.display();
    }
    return 0;
}

Text displayed while throwing exception is: "Unhandled exception in location 0x799B35BB (sfml-graphics-2.dll) 0xC0000005: Access violation while reading location 0x00000004"

c++
exception
sfml
asked on Stack Overflow Jul 21, 2020 by Thorvas

1 Answer

2

The main issue I can see is that in the constructor of FirstMenu you are

sf::Font font;
if (!font.loadFromFile("arial.ttf"))
{
    std::cout << "Font error. \n";
}
text.setFont(font)

Essentially setting the text's font to a local font object. This is problematic because text in SFML doesn't copy the passed in font resource.

SFML's documentation on the text class states this about setFont

The font argument refers to a font that must exist as long as the text uses it. Indeed, the text doesn't store its own copy of the font, but rather keeps a pointer to the one that you passed to this function. If the font is destroyed and the text tries to use it, the behavior is undefined.

It is also worth noting that the setTexture function for Shapes and Sprites behaves similarly as it doesn't store a copy of the texture resource.

The fix is to ensure that the font object is never destroyed while it is being used by a text object.

The simplest fixes include:

  1. Load the font in main and pass the font around to functions and objects that need it.
  2. If you are using a single font then have a global function that has a static font and constructs and loads it only once.
  3. If multiple fonts are needed and you don't want to pass the font around then you could have a singleton resource manager for fonts.
answered on Stack Overflow Jul 28, 2020 by Rabster

User contributions licensed under CC BY-SA 3.0