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

Author Topic: Drawing Text Access Violation  (Read 10065 times)

0 Members and 1 Guest are viewing this topic.

Gaius

  • Newbie
  • *
  • Posts: 11
    • View Profile
Drawing Text Access Violation
« on: August 14, 2014, 02:00:38 am »
call stack:

>   sfml-graphics-d-2.dll!std::_Tree<std::_Tmap_traits<unsigned int,sf::Font::Page,std::less<unsigned int>,std::allocator<std::pair<unsigned int const ,sf::Font::Page> >,0> >::_Lbound(const unsigned int & _Keyval) Line 2109   C++
    sfml-graphics-d-2.dll!std::_Tree<std::_Tmap_traits<unsigned int,sf::Font::Page,std::less<unsigned int>,std::allocator<std::pair<unsigned int const ,sf::Font::Page> >,0> >::lower_bound(const unsigned int & _Keyval) Line 1575   C++
    sfml-graphics-d-2.dll!std::map<unsigned int,sf::Font::Page,std::less<unsigned int>,std::allocator<std::pair<unsigned int const ,sf::Font::Page> > >::operator[](const unsigned int & _Keyval) Line 226   C++
    sfml-graphics-d-2.dll!sf::Font::getGlyph(unsigned int codePoint, unsigned int characterSize, bool bold) Line 295   C++
    sfml-graphics-d-2.dll!sf::Text::ensureGeometryUpdate() Line 269   C++
    sfml-graphics-d-2.dll!sf::Text::getLocalBounds() Line 214   C++
    Engine.exe!Text::getLocalBounds() Line 41   C++
    Engine.exe!Button::setTextSize(unsigned int textSize) Line 56   C++
    Engine.exe!Button::setString(std::basic_string<char,std::char_traits<char>,std::allocator<char> > text) Line 47   C++
    Engine.exe!Button::Button(std::basic_string<char,std::char_traits<char>,std::allocator<char> > text, unsigned int textSize, sf::Vector2<float> pos, sf::Color textColor, sf::Color buttonFaceColor) Line 7   C++
    Engine.exe!Missile_Command::initButtons() Line 56   C++
    Engine.exe!Missile_Command::init() Line 29   C++
    Engine.exe!Missile_Command::Missile_Command() Line 6   C++
    Engine.exe!main() Line 4   C++
    [External Code]   
    [Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]

code:
void Text::draw(sf::RenderTarget & target, sf::RenderStates states) const{
        target.draw(text);
}

which was called by:

void Button::draw(sf::RenderTarget & target, sf::RenderStates states) const{
        target.draw(buttonFace);
        target.draw(text);
}

No pointers were used to my knowledge.

The exact error is as follows:

Unhandled exception at 0x0F21F95C (sfml-graphics-d-2.dll) in Engine.exe: 0xC0000005: Access violation reading location 0x0000000D.

I've been trying to solve this for quite some time now. I think it has something to do with my sf::Text object not being properly initialized or something, but I couldn't find anything.

Here's the my Text class if anyone's interested:

(click to show/hide)

"text" and "font" are private class members.
« Last Edit: August 14, 2014, 02:05:04 am by Gaius »

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Drawing Text Access Violation
« Reply #1 on: August 14, 2014, 04:02:53 am »
As always, you need to show a complete and minimal example that demonstrates the problem. As it stands now there is no way to tell what you did wrong. You should also let us know what compiler you are using and where you got SFML.
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Gaius

  • Newbie
  • *
  • Posts: 11
    • View Profile
Re: Drawing Text Access Violation
« Reply #2 on: August 14, 2014, 04:37:55 am »
I am using Visual Studio 2013 Ultimate. I compiled SFML with cmake and I have been using that version for a few months now.

I changed my code now so that I don't use my Text class anymore but I am still getting the same error.

Button.cpp seems to be causing it now with it's derived draw method:
#include "init.h"


ui::Button::Button(std::string text, size_t textSize, sf::Vector2f pos, sf::Color textColor, sf::Color buttonFaceColor, std::string font){
        this->font.loadFromFile(font);
        this->text.setFont(this->font);
        setString(text);
        setPosition(pos);
        setTextColor(textColor);
        setButtonFaceColor(buttonFaceColor);
}

std::string ui::Button::getString() const{
        return text.getString();
}

EntityR ui::Button::getButtonFaceObj() const{
        return buttonFace;
}

sf::Vector2f ui::Button::getPosition() const{
        return buttonFace.getPosition();
}

sf::Vector2f ui::Button::getButtonFaceSize() const{
        return buttonFace.getSize();
}

size_t ui::Button::getTextSize() const{
        return text.getCharacterSize();
}

sf::Color ui::Button::getTextColor() const{
        return text.getColor();
}

sf::Color ui::Button::getButtonFaceColor() const{
        return buttonFace.getColor();
}

void ui::Button::setString(std::string text){
        this->text.setString(text);
        setTextSize(getTextSize());
}

void ui::Button::setPosition(sf::Vector2f pos){
        buttonFace.setPosition(pos);
        text.setPosition(pos + sf::Vector2f(10, 10));
}

void ui::Button::setTextSize(size_t textSize){
        text.setCharacterSize(textSize);
        float width = 100;//text.getLocalBounds().width;
        float height = 50;//text.getLocalBounds().height;
        buttonFace.setSize(width + 20, height + 20);
}

void ui::Button::setTextColor(sf::Color color){
        text.setColor(color);
}

void ui::Button::setButtonFaceColor(sf::Color color){
        buttonFace.setColor(color);
}

bool ui::Button::isPressed(sf::Event event){
        if (event.type == sf::Event::MouseButtonPressed){
                if (event.mouseButton.button == sf::Mouse::Button::Left){
                        sf::Vector2f mouseLoc(event.mouseButton.x, event.mouseButton.y);
                        if (cd::doesIntersect(mouseLoc, buttonFace))
                                return true;
                }
        }
        return false;
}

bool ui::Button::isHovering(sf::Mouse mouse){
        if (cd::doesIntersect((sf::Vector2f)mouse.getPosition(), buttonFace))
                return true;
        return false;
}

void ui::Button::draw(sf::RenderTarget & target, sf::RenderStates states) const{
        target.draw(buttonFace);
        target.draw(text);
}

Here's Button.h as well:
#pragma once

namespace ui{

        class Button : public sf::Drawable
        {
                EntityR buttonFace;
                sf::Font font;
                sf::Text text;
        public:
                Button(std::string text, size_t textSize, sf::Vector2f pos, sf::Color textColor, sf::Color buttonFaceColor, std::string font);
                Button(){}

                std::string getString() const;
                EntityR getButtonFaceObj() const;
                sf::Vector2f getPosition() const;
                sf::Vector2f getButtonFaceSize() const;
                size_t getTextSize() const;
                sf::Color getTextColor() const;
                sf::Color getButtonFaceColor() const;

                void setString(std::string text);
                void setPosition(sf::Vector2f pos);
                void setTextSize(size_t textSize);
                void setTextColor(sf::Color color);
                void setButtonFaceColor(sf::Color color);

                bool isPressed(sf::Event event);
                bool isHovering(sf::Mouse mouse);

                virtual void draw(sf::RenderTarget & target, sf::RenderStates states) const;
        };
}
 


And here is where it is called from (Missile_Command.cpp):
void Missile_Command::init(){
//...
        _quit = ui::Button("Quit", 32, sf::Vector2f(200, 200), sf::Color::Black, sf::Color(255, 255, 255, 128), "fonts/segoeuil.ttf");
        _start = ui::Button("Start", 32, sf::Vector2f(200, 300), sf::Color::Black, sf::Color(255, 255, 255, 128), "fonts/segoeuil.ttf");
}

void Missile_Command::run(){
        while (_window.isOpen()){
                //...
                _window.draw(_quit);
         _window.draw(_start);
//...
        }
}
« Last Edit: August 14, 2014, 04:44:05 am by Gaius »

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Drawing Text Access Violation
« Reply #3 on: August 14, 2014, 05:48:28 am »
Maybe "complete and minimal example" was not clear enough. :P

http://sscce.org/

Chances are pretty good that you have a problem with your code that has nothing to do with SFML directly
« Last Edit: August 14, 2014, 05:53:22 am by zsbzsb »
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Gaius

  • Newbie
  • *
  • Posts: 11
    • View Profile
Re: Drawing Text Access Violation
« Reply #4 on: August 14, 2014, 06:35:24 pm »
I'm fairly new to SFML, so the problem most likely lies with my code.
Minimal working example:

#include <SFML/Graphics.hpp>
class Text : public sf::Drawable
{
        sf::Font font;
        sf::Text text;
public:
        Text(std::string string){
                if (!font.loadFromFile("segoeuil.ttf")) // Nothing wrong with loading the font
                        std::exit(-1);
                text = sf::Text(string, font, 30);
        }
        Text(){ }

        virtual void draw(sf::RenderTarget & target, sf::RenderStates states) const{
                target.draw(text);
        }
};

int main(){
        sf::RenderWindow window(sf::VideoMode(800, 600), "Text test");

        Text text("Text");
    //Text text; -> same result

        // Error (on draw) -> Access Violation
        // Commenting this line out, solves the problem
        text = Text("Text");
       

        while (window.isOpen()){
                window.clear();
                window.draw(text);
                window.display();
        }

        return 0;
}
« Last Edit: August 14, 2014, 06:46:18 pm by Gaius »

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Drawing Text Access Violation
« Reply #5 on: August 14, 2014, 06:48:02 pm »
Well copying your text and font instance while destroying the previous instances without updating the new text's font pointer is a sure way to get a memory violation.

http://en.cppreference.com/w/cpp/language/as_operator
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Drawing Text Access Violation
« Reply #6 on: August 14, 2014, 06:59:32 pm »
Adding to what zsbzsb said, since it might not be as simple to everyone who stumbles on this thread.

There is nothing wrong with SFML. What you consider an error is actually a "feature" ;D, or at least intended behaviour.

When you copy the sf::Font, it does a standard copy, member by member. When you copy the sf::Text, it does a standard copy, member by member. Now, what might go wrong there? For that you have to understand how sf::Text stores the reference to the sf::Font it uses, through a pointer. This means that when you create an sf::Font to be used with your sf::Text inside the class, that is the only place where you are allowed to use them with each other.

When you copy them from one object to another, the sf::Text is kind of dumb (for lack of a better word) in that it has no knowledge of where the sf::Font really is, so it just copies the sf::Font pointer anyway. What happens when your Text object gets destroyed? The sf::Font contained in it gets destroyed with it, but the pointer that was copied out earlier doesn't get updated. This means that when the new sf::Text object tries to do anything that requires a font, it still tries to access the old, destroyed one, and you have a problem. This is what happens when you assign a temporary Text object to your existing one (assignments are like copies, just to keep things simple). The temporary only exists for the duration of the assignment and gets destroyed thereafter.

What can you do to fix this? Employ your own copy constructor or assignment operator (link provided by zsbzsb), where you copy the members yourself and call setFont() to update the internal font pointer to the correct value. Make sure to do this after you copy the members, and not before, for obvious reasons.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Gaius

  • Newbie
  • *
  • Posts: 11
    • View Profile
Re: Drawing Text Access Violation
« Reply #7 on: August 14, 2014, 07:50:15 pm »
Thanks, That helped me solve the issue.