• Advertisement
Sign in to follow this  

Memory management

This topic is 975 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

At the moment, I'm using a std::vector of std::unique_ptr.

I push state objects created with std::make_unique using std::move when I want to change state and then I erase the stack.

I'm testing things out using 2 states: one has some textures in it and the other one is empty.

What happens when I repeatedly switch between states is that memory usage increases by 5mb per switch.

I also tried making the textures raw pointers. When I manually delete them before switching states there is no increase in memory. But if I try to make them shared pointers or unique pointers the memory will still increase.

I'm curious how should I handle these states and pointers.

This is the code:

void StateManager::changeState(std::unique_ptr<State> state)
{
    //If the vector isn't empty destroy the current states
    //Clear the vector
    if (states.empty() == false)
    {
        for (auto i = 0; i < states.size(); i++)
        {
            states[i]->destroy(*window);
        }
        states.clear();
    }

    //Move the new state inside the vector
    states.push_back(std::move(state));

    //Initiate the state
    if (states.empty() == false)
    {
        states[MAINSTATE]->init(*window);
    }
}

Share this post


Link to post
Share on other sites
Advertisement
That code looks fine (other than that tortured `states.empty() == false` instead of the far simpler `!states.empty()`), but it sounds like this code has nothing to do with the problem (texture memory management).

Share this post


Link to post
Share on other sites
Is State::~State virtual? Otherwise, the destructors of the children types will not be called and cleanup (outside of destroy) will be skipped.

Share this post


Link to post
Share on other sites

I'm curious why you would have explicit init/destroy calls that get manually invoked after/before the constructor and destructos of your State class.  WHat would happen if you moved those functions into the constructor/destructor?

Share this post


Link to post
Share on other sites

Ok, due to lack of understanding here is my State class:

#ifndef STATE_H
#define STATE_H

#include "Globals.h"

class State
{
public:
    virtual void init(sf::RenderWindow &window) = 0;
    virtual void update(sf::RenderWindow &window, float dt) = 0;
    virtual void draw(sf::RenderWindow &window) = 0;
    virtual void handleEvents(sf::RenderWindow &window, sf::Event &event) = 0;
    virtual void destroy(sf::RenderWindow &window) = 0;
};

#endif

It is a pure virtual class, thus it has no constructors/destructors.

 

And here is my MenuState class in which I load some textures:

#include "MenuState.h"
#include "PlayState.h"

void MenuState::init(sf::RenderWindow &window)
{
    WIDTH = window.getSize().x;
    HEIGHT = window.getSize().y;
    std::cout << "MENUSTATE" << std::endl;
    playState = false;

    m_textureNormal = std::make_shared<sf::Texture>();
    m_textureNormal->loadFromFile("data/texture.png", sf::IntRect(0, 0, 64, 64));

    m_textureFlag = std::make_shared<sf::Texture>();
    m_textureFlag->loadFromFile("data/texture.png", sf::IntRect(128, 0, 64, 64));

    m_textureBomb = std::make_shared<sf::Texture>();
    m_textureBomb->loadFromFile("data/texture.png", sf::IntRect(192, 0, 64, 64));
    
    m_textureClicked = std::make_shared<sf::Texture>();
    m_textureClicked->loadFromFile("data/texture.png", sf::IntRect(256, 0, 64, 64));
    
}

void MenuState::update(sf::RenderWindow &window, float dt)
{
    
}

void MenuState::draw(sf::RenderWindow &window)
{

}

void MenuState::handleEvents(sf::RenderWindow &window, sf::Event &event)
{
    if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::P)
        state_manager.changeState(std::unique_ptr<State>(std::make_unique<PlayState>()));
}

void MenuState::destroy(sf::RenderWindow &window)
{
    /*delete m_textureNormal;
    delete m_textureFlag;
    delete m_textureBomb;
    delete m_textureClicked;*/
    
}

I also have a PlayState but that class is empty.
If I switch to PlayState and then back to MenuState the RAM increases by ~5mb and keeps doing so. One quick fix was to use raw pointers for the textures and then delete them in the "destroy" method but I don't like the idea of using them because it is "bad practice".

The most ideal solution would be to not use pointers at all but even if I don't use raw/smart pointers for the textures the RAM still increases.

The only solution as of right now is to use raw pointers. I'm asking if there is any other fix.

Share this post


Link to post
Share on other sites

So I ended up putting this in there:

virtual ~State() {};

For some reason the RAM still grows but after 5-6 switches between states it stabilizes. ohmy.png

I guess that solved it. Not to sure about why it keeps growing in the beginning though. Thank you!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement