0

I'm making a small game using SFML 2.2

I'll start with my code. As I already had about 4000 lines of working code I made a texture manager for storing all textures that are used at a time. I used texures earlier of course but I needed a way to manage them. It looks like this:

//Declarations

class Manager
{
private:
    static map<string, Texture > textures;
public:
    static Texture & add(const string & name, const string & directory);
    static Texture & resolve(const string & name);
};

//Definitions

Texture & Manager::add(const string & name, const string & directory)
{
    // Check, whether a said texture was already maped
    map<string, Texture>::const_iterator it = textures.find(name);
    if (it != textures.end())
    {
        cout << "Said element was loaded" << endl;
        return textures.at(name);
    }

    // Adding a new texture
    Texture tex;
    tex.loadFromFile(directory);
    textures[name] = tex;

    cout << "Texture added" << endl;
    return textures.at(name);
}

Texture & Manager::resolve(const string & name)
{
    cout << "Resolved" << endl;
    return textures.at(name);
}

map<string, Texture > Manager::textures;

As you can see I have a global map accesed by two methods. Both methods return a reference to a certain texture. So as my project had already quiet a lot of textures I decided to check if my manager works fine and replaced loading one texture with method add and binding it to sprite with resolve. As I compiled code and run it everything worked good untill I went back to menu of my game and decided to "play again". Now, when it came to load the texture again, method add correctly recognized name (key) as already used and method resolve returned correctly texture. At least "Resolved" appeared on the screen. And this is the point when error ocures.

But when I moved calling add from method, where the texture is used to the constructor of the class that uses it, it works fine again. And it's called the same amount of times; once per "play game".

Here is the not working code:

void Engine::set_up(int & lvl)
{
    srm::Manager::add("Loading screen", "data/loading_screen.png");

    Sprite spr;
    spr.setTexture(srm::Manager::resolve("Loading screen"));

    // ...
}

Also not working code:

void Engine::set_up(int & lvl)
{
    Sprite spr;
    spr.setTexture(srm::Manager::add("Loading screen", "data/loading_screen.png");

    // ...
}

And working:

//Constructor
Engine(){ srm::Manager::add("Loading screen", "data/loading_screen.png"); }

//Method
void Engine::set_up(int & lvl)
{    
    Sprite spr;
    spr.setTexture(srm::Manager::resolve("Loading screen"));

    // ...
}

I feel I made a mistake in my Manager. Here is what the error says:

Microsoft Visual C++ Runtime Library - Error

There is used word "heap" so it just confirmed me that those error is related to my Manager. I made a research in the web and I have found this:

Debug Assertion Failed: _CrtIsValidHeapPointer(pUserData)

I understand what cause the error but I can't understand where my mistake is. The weirdest thing is that those calling add in constructor works and calling it elsewhere doesn't!

I'm sorry if something isn't clear, I'll answer your questions then.

Does anybody know any solution to this issue? Can you explain me, what's wrong in my code? Thank you in advance!


EDIT

Ok, I tracked stack in debug mode and found the culprit. These are sf::Text objects which have in field value

Information not avaliable, no symbols loaded for sfml-graphics-d-2.dll

and in every test it appears in other Text object. Always there are problems with strings, it's always "Unable to read memory" in string parts of my texts. I don't know why, for me it's not even related to my problem. However, when I changed my code back to this:

void Engine::set_up(int & lvl)
{
    //srm::Manager::add("Loading screen", "data/loading_screen.png");
    Texture texture;
    texture.loadFromFile("data/loading_screen.png");
    Sprite spr;
    spr.setTexture(texture);
    //spr.setTexture(srm::Pojemnik::zwroc("Ekran wczytywania"));

so a classic local sf::Texture object and binding it to sprite, everything works perfectly with no problem.

So as I said, when I put

srm::Manager::add("Loading screen", "data/loading_screen.png");

to the constructor or when I don't use my Manager class at all everything works, when I want to use my code - it hangs.

Community
  • 1
  • 1
Skorpion
  • 21
  • 1
  • 9
  • Your code does not compile (`Pojemnik::tekstury` does not exist, additional `;` in second non-working example). If those are fixed, all 3 version work for me. Can you give a SSCCE where the problem occurs? – king_nak Feb 07 '16 at 12:45
  • 1
    One possible bug is in `resolve` though. If you try to resolve a texture that was never added, you get a invalid reference! You might want return a pointer instead, and return `nullptr` if the texture was not loaded. – king_nak Feb 07 '16 at 12:47
  • king_nak, those two mistakes are because I translated my code to english and fixed right now. I don't know how to give a SSCCE in this case, can you suggest something? I never have an invalid reference in my test. But thank you, it is indeed a thing to improve. – Skorpion Feb 07 '16 at 12:54
  • It is not going to be an easy problem to diagnose, especially not from a remote location. The error message is a debug-library diagnostic telling you that you've somehow corrupted the heap—perhaps when allocating memory, perhaps by mismatching calling conventions, or a whole host of other things. The corruption may not have even been at the exact location where the problem is being detected, it could have been anywhere in your code. You can start narrowing down the problem by breaking into the debugger when you see the message and looking at the "Call Stack" window to get your bearings. – Cody Gray - on strike Feb 07 '16 at 13:04
  • @CodyGray look at the question - I edited it, maybe it could help. – Skorpion Feb 07 '16 at 14:54

0 Answers0