Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Memory Violation odd error with sf::Sprite  (Read 2546 times)

0 Members and 1 Guest are viewing this topic.

Canvas

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Memory Violation odd error with sf::Sprite
« on: January 11, 2015, 08:03:15 pm »
Hello there,

I have myself a ImageLoader which stores a vector of sf::Textures. now here is the odd problem I am having, I have myself a class known as UserInterface.

Here is the header file
#pragma once

#include "SFML\Graphics.hpp"
#include "ImageLoader.h"
#include <vector>

class UserInterface
{
private:
        ImageLoader& _imageLoader;
public:
        int SelectedPower;
        int Powers[9];
        sf::Sprite Bar;
        std::vector<sf::Sprite> PowerUpIcons;
        sf::Sprite PowerSelected;

        UserInterface(ImageLoader& imageLoader);
        ~UserInterface();

        void Setup();
        void SetupPowerUps();
        void Draw(sf::RenderWindow& window);
        void Update();
        void AddPower();
};

Here is the cpp file
#include "UserInterface.h"

UserInterface::UserInterface(ImageLoader& imageLoader) :
_imageLoader(imageLoader)
{
        SelectedPower = 0;
        Powers[1] = 0;
        Powers[2] = 0;
        Powers[3] = 0;
        Powers[4] = 0;
        Powers[5] = 0;
        Powers[6] = 0;
        Powers[7] = 0;
        Powers[8] = 0;
        Powers[9] = 0;
}

UserInterface::~UserInterface()
{

}

void UserInterface::Setup()
{
        Bar.setTexture(_imageLoader.Images[ImageNames::UI_BottomBar]);
        Bar.setPosition(0, 675);

        PowerSelected.setTexture(_imageLoader.Images[ImageNames::UI_Power_Selected]);
        PowerSelected.setPosition(-100, -100);

        SetupPowerUps();
}

void UserInterface::SetupPowerUps()
{
        for (int i = 0; i < 9; i++)
        {
                sf::Sprite newSprite;
                switch (i)
                {
                case 0: newSprite.setTexture(_imageLoader.Images[ImageNames::UI_Power_Up1]); break;
                case 1: newSprite.setTexture(_imageLoader.Images[ImageNames::UI_Power_Up2]); break;
                case 2: newSprite.setTexture(_imageLoader.Images[ImageNames::UI_Power_Up3]); break;
                case 3: newSprite.setTexture(_imageLoader.Images[ImageNames::UI_Power_Up4]); break;
                case 4: newSprite.setTexture(_imageLoader.Images[ImageNames::UI_Power_Up5]); break;
                case 5: newSprite.setTexture(_imageLoader.Images[ImageNames::UI_Power_Up6]); break;
                case 6: newSprite.setTexture(_imageLoader.Images[ImageNames::UI_Power_Up7]); break;
                case 7: newSprite.setTexture(_imageLoader.Images[ImageNames::UI_Power_Up8]); break;
                case 8: newSprite.setTexture(_imageLoader.Images[ImageNames::UI_Power_Up9]); break;
                }
               
                newSprite.setPosition(328 + (i * 41), 700);
                newSprite.setTextureRect(sf::IntRect(0, 0, 38, 38));
                PowerUpIcons.push_back(newSprite);
        }
}

void UserInterface::Update()
{
        PowerSelected.setPosition(328 + ( (SelectedPower - 1) * 41), 700);
}

void UserInterface::Draw(sf::RenderWindow& window)
{
        sf::View tempView(sf::FloatRect(0, 0, window.getSize().x, window.getSize().y));
        window.setView(tempView);

        //Bar.setTexture(_imageLoader.Images[ImageNames::UI_Power_Selected]);
        //Bar.setPosition(0, 640);

        window.draw(Bar);

        for (int i = 0; i < PowerUpIcons.size(); i++)
        {
                window.draw(PowerUpIcons.at(i));
        }

        window.draw(PowerSelected);
}

void UserInterface::AddPower()
{
        SelectedPower++;
}

Now basically if you look at my Setup function it sets up the Bar sf::Sprite and sets up the PowerSelected sf::Sprite, it sets the texture and also sets the position, now in my Draw function, it sets up a view and then draws out the bar, my powers and powerselected sprite. however when it attempts to draw Bar it comes up with this error

Unhandled exception at 0x0F1BE57E (sfml-graphics-d-2.dll) in ColourGalaxy.exe: 0xC0000005: Access violation reading location 0x00000004.
this error is thrown in function
void RenderTarget::draw(const Drawable& drawable, const RenderStates& states)
{
    drawable.draw(*this, states);
}
Look at the image attached to see my error.

Now here is the bit that confuses me. If I comment out my window.draw(Bar); everything works fine. so if though I am setting up my PowerSelected sf::Sprite in the same function as the Bar variable. PowerSelected has no problem at all being drawn. Can anyone help me understand why my Bar variable is causing the memory violation?

Canvas

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Re: Memory Violation odd error with sf::Sprite
« Reply #1 on: January 11, 2015, 08:23:39 pm »
Just to let you guys know, I changed my header file like so

#pragma once

#include "SFML\Graphics.hpp"
#include "ImageLoader.h"
#include <vector>

class UserInterface
{
private:
        ImageLoader& _imageLoader;
        bool setup;
public:
        int SelectedPower;
        int Powers[9];
        std::vector<sf::Sprite> PowerUpIcons;
        sf::Sprite BottomBar;
        sf::Sprite PowerSelected;

        UserInterface(ImageLoader& imageLoader);
        ~UserInterface();

        void Setup();
        void SetupPowerUps();
        void Draw(sf::RenderWindow& window);
        void Update();
        void AddPower();
};

I moved my sf::Sprite BottomBat sprite below the std::vector and now I don't get an error. This is sweet because it is fixed but still why would I get this error?

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
AW: Memory Violation odd error with sf::Sprite
« Reply #2 on: January 11, 2015, 08:43:42 pm »
It's probably pure luck. Not sure if that is the issue, but you're accessing an element beyond the array. C++'s indecies start with 0. So if you have a size of 9, the indecies have to be 0-8 and not like in your code 1-9.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: Memory Violation odd error with sf::Sprite
« Reply #3 on: January 11, 2015, 09:40:27 pm »
I have myself a ImageLoader which stores a vector of sf::Textures.
I wouldn't store Textures in a vector. At least not unless you've called reserve() on it first to pre-allocate enough memory for the maximum number of elements it will ever hold.
If you don't reserve() and the vector then reallocates when you insert an element then it will copy the old elements to the new storage which will invalidate all iterators, pointers and references to the old objects. This will leave all sprite objects refering to Texture objects which have been destroyed and buy you a first class ticket to undefined behaviour land when those sprites subsequently try to access their textures.
Not to mention that Textures are fairly expensive objects to copy.
Of course a vector can work. You just need to be very careful and know when iterators etc become invalid and then deal with that. A std::vector<std::unique_ptr<sf::Texture>> would probably be a better choice (or one of the node based containers).
« Last Edit: January 11, 2015, 09:47:59 pm by Jesper Juhl »

Canvas

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Re: Memory Violation odd error with sf::Sprite
« Reply #4 on: January 11, 2015, 11:18:20 pm »
Thank you Jesper Juhl for that however my std::vector seems to be working fine for me, also my vector holds the textures and when I setup a new sprite i provide it a pointer to a texture that is stored int eh std::vector. eXpl0it3r what you said is true but it wasn't the cause, but yea just moving the variables seemed to work :)