1

I am trying to print text to a specific spot on my window through a function within a separate class from main. This function basically updates the string in the text and then the text is later drawn in the main loop. However, every time I try running, it gives me a white screen and exits with code -1073741819. This is what the code looks like: THIS IS IN MAIN:

sf::Font txt_font;
    txt_font.loadFromFile("F:\\C++VS\\Rigid_Ball_Physics\\Rigid_Ball_Physics\\arial.ttf");
    if (!txt_font.loadFromFile("F:\\C++VS\\Rigid_Ball_Physics\\Rigid_Ball_Physics\\arial.ttf"))
    throw("FAILED TO LOAD FONT");
ball.update_ball_vectors();
        overlay.UPDATE(txt_font);

THIS IS THE SEPARATE FUNCTION

void INFO_DISPLAY::render_info_text(sf::Font font)
{
    object_info_label.setFont(font);
    object_info_label.setPosition(sf::Vector2f(0, 0));
    object_info_label.setFillColor(sf::Color::Black);
}
void INFO_DISPLAY::update_info_display(
    int selected_object,
    float ball_radius,
    sf::Vector2f ball_position,
    sf::Vector2f ball_velocity)
{
    object_info_label.setString(
        "SELECTED OBJECT: " + std::to_string(selected_object) + "\n" +
        "RADIUS: " + std::to_string(ball_radius) + "\n" +
        "POSITION_X: " + std::to_string(ball_position.x) + "\n" +
        "POSITION_Y: " + std::to_string(ball_position.y) + "\n" +
        "VELOCITY_X: " + std::to_string(ball_velocity.x) + "\n" +
        "VELOCITY_Y: " + std::to_string(ball_velocity.y) + "\n"
    );
}
MAIN_OVERLAY::MAIN_OVERLAY(sf::Font font)
{
    ID.set_info_display_position(0.0f, 0.0f);
    ID.render_info_text(font);<--------------|THIS HERE
    UI.set_user_interface_position(main_window_width - (UI.user_interface_width - 2), main_window_height - UI.user_interface_height);
}

I looked for others with similar issues, but the only one I could find had an answer about the font not being created in main.cpp, and so I did not exist outside of the separate class and Text was referring to no font. I fixed this in mine (or so I think) and the same problem persists.

Yubi
  • 11
  • 3
  • The problem may come from the fact that sf::Font has to stay alive to work, and that SFML objects do not copy fonts but instead keep a reference to it. Since you're passing your sf::Font as a copy in render_info_text, it probably dies right after the function ends. – Axel.A Dec 20 '22 at 15:33
  • @Axel.A do you know how I could fix that, I am currently super stumped on it. – Yubi Dec 21 '22 at 14:20
  • I don't know where do you store your sf::Font, but if it stays alive, just pass it as a reference to your function. "void INFO_DISPLAY::render_info_text(sf::Font font)" becomes "void INFO_DISPLAY::render_info_text(sf::Font& font)". This way you are not passing a **copy** to the font but a reference. By the way, do you understand what I mean when I say that it has to _stay alive_? – Axel.A Dec 21 '22 at 15:01
  • 1
    @Axel.A I understand what you mean now, and I think I understand, but I'm not completely sure if I have the right idea in mind. Staying alive means that the object has a valid memory location or something like that, right?Also, the font is being created in main as I was planning on using it across my whole program – Yubi Dec 21 '22 at 18:32
  • I wrote a more detailed answer to explain the problem. Glad that it helped you. – Axel.A Dec 22 '22 at 08:50

1 Answers1

0

Your problem is that in the SFML, most methods that takes a sf::Font as a parameter do store it as a reference to a sf::Font object. The issue is that in every method that you wrote, you pass the sf::Font as a copy and not as a reference, which means that the sf::Font is copied for the purpose of the function call and dies right after the function finishes. It leads to objects having a reference to a dead sf::Font.

Here is a simple example to understand what happens in your code:

#include <stdio.h>
#include <string>
#include <iostream>

class Font
{
public:
    Font(const std::string & fontPath)
    {
        fontPath_ = fontPath;
    }

    std::string getPath() const
    {
        return fontPath_;
    }
    
private:
    std::string fontPath_;
    
};


class Text
{
public:
    Text(Font &font)
    : textFont_(font)
    {

    }
    
    Font &getFont()
    {
        return textFont_;
    }
    
private:
    Font &textFont_;
};


/*
    This function is not valid because "font" was passed as value and not as reference
    That means that at the end of the function "font" is automaticaly destroyed
    because it is out of scope.
    So "text" has a reference to an object that do not exist anymore
*/

Text bugged_create_text(Font font)
{
    Text text(font);

    return text;
    
}


/*
    Same problem, "font" is created in the function, that means that when the function finishes,
    "font" will be destroyed.
*/

Text bugged_create_text2()
{
    Font font("fake/path/to/my/font");
    Text text(font);

    return text;
    
}

/*
    This works because in this context, writing "Font& font" means that our "font" parameter is a reference, not a copy
    In this example, the font directly point to the memory of the "font" we created in the main
    So it is not destroyed after the function is finished
*/

Text working_create_text(Font& font)
{
    Text text(font);

    return text;
}



int main()
{
    Font myFont("fake/path/to/my/font");
    
    // OK
    Text text1 = working_create_text(myFont);
    Font& text1_font = text1.getFont();
    
    std::cout << text1_font.getPath() << std::endl;
    
    
    // Crashes or Undefined Behavior
    // Undefined Behavior explanation: https://www.geeksforgeeks.org/undefined-behavior-c-cpp/#:~:text=So%2C%20in%20C%2FC%2B%2B%20programming,exactly%20what%20the%20programmer%20intended.
    Text text2 = bugged_create_text(myFont);
    Font& text2_font = text2.getFont();
    
    std::cout << text2_font.getPath() << std::endl;
    
    // Crashes or Undefined Behavior 2
    Text text3 = bugged_create_text2();
    Font& text3_font = text3.getFont();
    
    std::cout << text3_font.getPath() << std::endl;
    
    
}

More to read about references, lifetime of a variable and Undefined Behavior

Axel.A
  • 94
  • 1
  • 9