'SFML Ressource Manager class , null pointer on textures

I wrote a chess game and am now trying to change the design to include a Ressource Manager class (I have heard this is more efficient?). I am having issues though with null pointers regarding textures. I am getting the same errors both in this minimal example and on my main application.

Expected behavior

I am expecting 4 circles to appear on the screen distanced by 100 pixels.

Actual behavior

The screen flashes, then closes immediately with a segmentation fault

Minimally Reproducible Example

RessourceManager.hpp

#pragma once
#include <vector>
#include <unordered_map>
#include <SFML/Graphics.hpp>
#include <memory>

using namespace std;

typedef unordered_map<string, shared_ptr<sf::Texture>> textureMap;

class RessourceManager {  
    string m_textureNames[1] = {"circle.png"};
    textureMap m_textures;

    public:
    RessourceManager(); // Constructor

    void loadRessources();
    void addTexture(const string& name);
    shared_ptr<sf::Texture> getTexture(const string &name);
};

RessourceManager.cpp

#include "RessourceManager.hpp"
#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

RessourceManager::RessourceManager() {};

void RessourceManager::addTexture(const string& name) { 
    shared_ptr<sf::Texture> texture = make_shared<sf::Texture>();
    texture->loadFromFile(name);
    m_textures.emplace(name, move(texture));
};

shared_ptr<sf::Texture> RessourceManager::getTexture(const string &name) {
    for(auto it = m_textures.begin();it != m_textures.end(); ++it) {
        if(it->first == name) {
            cout << "found" <<endl;
            return move(it->second);
        }
    }
    return nullptr;
};

void RessourceManager::loadRessources() {
    for(size_t i = 0; i < 1; ++i)  addTexture(m_textureNames[i]);
}

main.cpp

#include <SFML/Graphics.hpp>
#include "RessourceManager.hpp"

void drawSquares(sf::RenderWindow&, RessourceManager&);

int main(){
    sf::RenderWindow window(sf::VideoMode(600, 480), "SFML window");
    RessourceManager ressources; 
    ressources.loadRessources();

    while (window.isOpen()){
        sf::Event event;
        while (window.pollEvent(event)){
            if (event.type == sf::Event::Closed) window.close();
        }
        drawSquares(window, ressources);
        window.display();
    }
    return 0;
}

void drawSquares(sf::RenderWindow& window ,RessourceManager& ressources) {
    for(int i = 20; i <= 320; ++i) {
        shared_ptr<sf::Texture> temp = ressources.getTexture("circle.png");
        sf::Sprite s(*temp);
        s.setPosition(i, i);

        window.draw(s);
    }
}

Output console

found
found
[1]    4445 segmentation fault  sudo ./main

Aditional information

Here I am using shared_ptr because I want multiple Sprites to point to the same texture (for instance 8 black pawns or 8 white pawns in a chess game). Further, I need these textures to move dynamically around on the screen so I must have them in the main loop in a standalone function.

Things I have tried

  1. In drawSquares() I tried to first define an array shared_ptr<sf::Texture> textures[5];, populate it with the textures returned from ressources.getTexture() and then use these textures on the sprites in the for loop, but with no success.
  2. I have tried using unique_ptr
  3. I have tried to write sf::Sprite s(*(ressources.getTexture("circle.png"))); immediately, but also doesn't work.
  4. I have read the SFML documentation on Textures and c++ variable scope/life time information, but I still can't understand what I am doing wrong in here.


Solution 1:[1]

Answer was found

Thanks to metaquarks on Discord, removing the move() wrappers in move(it -> second) and .emplace(name. move(texture)) fixed the problem.

This is because after calling get(), the only thing keeping the texture alive is the pointer that was returned which is in this example dereferenced and passed as a non-owning reference, so it just dies. If one does not return using move(), both shared pointers keep it alive, and when the returned one eventually goes out of scope, it still exists because it is inside the map.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 hexaquark