0
votes

This is a C++ memory management problem thus I chose to ask here. I am creating a game in SFML. I have used SDL before and managing my Textures was very straightforward but SFML works differently.

My project setup is something like so:

class Game
//create window and initialize game stuff

class Character
/*initializes its own textures and is also responsible for updating itself
as well as drawing itself*/

int main()
/*create an instance of Game -> Create an instance of Character and
runGame. I will implement the drawing and updating properly when I 
implement a scene graph and scene nodes but for now updating and drawing is 
done via global functions called by the Game Class*/

The challenge I faced was that using an sf::Texture in the Character class for the Sprite image results in a white rectangle being drawn. So the Character Sprite loses its Texture link and SFML just draws a white rectangle. To solve this I created a raw Texture pointer and Initialize it in the Character constructor. This works and the Sprite is drawn correct.

//inside character.hpp
sf::Texture *texture;

//in Character constructor
texture= new (sf::Texture);

This means I have to manage the memory and the code feels ugly.

I have tried this to manage the memory allocated (I think) to prevent a memory leak:

Character::~Character()
{ delete texturePtr; }

but that is wrong obviously. I also tried to delete character.Texture at the end of main() when I exit the application but that causes an error also.

I then tried to do use a uinque_ptr inside the Character constructor:

std::unique_ptr<sf::Texture> texture(new sf::Texture);
//load Texture from Resource Manager instance

and this draws a nice navy blue-black rectangle instead of the Sprite Texture. I am not sure how or if I can declare and then later initialize a unique_ptr.

I think I am leaking memory and if so, how do I correctly use the smart pointers or manage my own memory properly?

I have added a bit more detail and code as I realized I was being vague. Also, I am querying the texture and using it to set the Sprite Rect dimensions so it is definitely being loaded, but just to be safe, I have a logger function that checks if any resource I call is loaded or not.

1
You haven't given us enough code to see what you're doing wrong. That said, using unique_ptr is probably a good idea. If your texture is coming out blue, that sounds like an initialisation bug. Also, consider using make_unique instead of unique_ptr<...> foo(new whatever). - Rook
You said you had problems with your old way of doing it... but never asked about it. You are looking for solutions to a problem you should not even have. You should ask the question about your first problem of the white sprites. - nvoigt
Don't use 'new' here, nor a pointer. See official example sfml-dev.org/tutorials/2.5/graphics-sprite.php - scape

1 Answers

2
votes

If the sf::Texture is a member of Character then it will not go out of scope until your Character instance does.

Use the debugger break points to follow what happens. Throw a break point in the destructor of Character and sf::Texture and walk through your startup and shutdown sequences. Or use Log to print messages like: "Character::~ called."


I think I am leaking memory and if so, how do I correctly use the smart pointers or manage my own memory properly?

Question all assumptions, including the one that you are loading the texture properly. Until you see the texture draw on screen, you don't have evidence that you have loaded it. (Unless you want a navy-blue rect. I don't know what you are trying to draw. I assume a character sprite.)

From SFML Docs:

The loadFromFile function can sometimes fail with no obvious reason. First, check the error message that SFML prints to the standard output (check the console). If the message is unable to open file, make sure that the working directory (which is the directory that any file path will be interpreted relative to) is what you think it is: When you run the application from your desktop environment, the working directory is the executable folder. However, when you launch your program from your IDE (Visual Studio, Code::Blocks, ...) the working directory might sometimes be set to the project directory instead. This can usually be changed quite easily in the project settings.

Until you see a leak in a leak detector, you really can't assume that you are leaking memory. There are 3rd party memory trackers you can add to your program.

Again, use a debug break point in sf::Texture destructor to stop execution and see exactly where you are deallocating (if this turns out to be the problem).


You really should read and follow Minimal, Complete, and Verifiable example. For all we know you could be doing something like this:

class Character{
    sf::Sprite mySprite;

    public:
    Character(){
        sf::texture aTex;
        aTex.loadFromFile("c:\users\noob\Desktop\myawesomegame\stripper.png");

        mySprite.setTexture(aTex);
    }
}

// attempt 2
class Character{
    sf::Sprite mySprite;

    public:
    Character(){
        std::unique_ptr<sf::Texture> texture(new sf::Texture);
        texture->loadFromFile("c:\users\noob\Desktop\myawesomegame\stripper.png");

        mySprite.setTexture(*texture);
    }
}

And the error would be obvious.