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

Author Topic: Segfault "Access not within mapped region at address 0x10" in RenderTarget::draw  (Read 9714 times)

0 Members and 1 Guest are viewing this topic.

anthonyy

  • Newbie
  • *
  • Posts: 11
    • View Profile
    • Email
Hey,

I need another pair of eyes to look over my code to find out what the hell is going on :P

I get no compiler or link errors but I segfault every time, upon closer inspection with Valgrind, I am given an error message:

Access not within mapped region at address 0x10
==21451==    at 0x52A31B6: sf::RenderTarget::draw(sf::Drawable const&, sf::RenderStates const&) (in /usr/local/lib/libsfml-graphics.so.2.4.1)
 

It crashes during this function:

void
render_system_draw(Engine *engine, EntityPool &pool) {
    std::shared_ptr<TransformComponent> transform;
    std::shared_ptr<RenderComponent> render;

    for (Entity *ent : pool.entities) {
        if (entity_has_component<TransformComponent>(ent) && entity_has_component<RenderComponent>(ent)) {
            transform = entity_get_component<TransformComponent>(ent);
            render = entity_get_component<RenderComponent>(ent);

            render->sprite.setPosition(sf::Vector2f(transform->x, transform->y));

            engine->window.draw(render->sprite); /* CRASHES HERE */

        }
    }
}
 

render->sprite is an sf::Sprite, the texture is maintained since I do all my allocations in a big pool and give out sub-allocations so it only gets freed at the end. I've got into the debugger and poked around, double-triple checking that render->sprite is not null, nor is engine or the entity pool.

If I move the draw code out into game.cpp, and use a separate texture and position, it works fine. But as soon as I call it in render_system_draw, it segfaults. render and texture are not null, nor is any of their members.

Help please :P

If you need to see any more code then just say and I'll post whatever you need.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Build with debug symbols and provide the call stack up on crash. As well as your OS, GPU and used GPU driver.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

anthonyy

  • Newbie
  • *
  • Posts: 11
    • View Profile
    • Email
Already building with debug symbols.

Here's the call stack:

render_system_draw(Engine *engine, EntityPool &pool)
render(Engine *engine, GameState *state)
main(int argc, char **argv)

OS: Xubuntu 16.04 LTS
GPU: NVIDIA GTX 750 Ti
GPU driver: proprietary NVIDIA version 367.57

I've also just rebuilt SFML from source again and done a clean reinstall to make sure there are no conflicts, no prebuilt packages for SFML are on my system either.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
If that's the full call stack, then the error is within your code. Since you do a lot of point magic (why are you not using references), chances are that one pointer simply is a nullptr, leading to a crash.

If that's not the full call stack, then build SFML with debug symbols and actually provide the full call stack. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

anthonyy

  • Newbie
  • *
  • Posts: 11
    • View Profile
    • Email
Okay I've basically done a full refactor and it seems to be working correctly now. I think it was a collection of dumb mistakes. Feel free to delete this topic.

anthonyy

  • Newbie
  • *
  • Posts: 11
    • View Profile
    • Email
Okay nevermind lol

I've found that the problem only persists when my Render component is allocated on the heap. If it's on the stack, it works fine but it's pretty impractical to store my components on the stack.

Anyone have any ideas what could be causing this?

From the start I was never saying it's a problem with SFML I was simply asking if anybody knew what was wrong.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
What does entity_get_component<RenderComponent>(ent) do?
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

anthonyy

  • Newbie
  • *
  • Posts: 11
    • View Profile
    • Email
I've since refactored and renamed stuff but the concept is the same. Here is the implementation of Entity just copy-pasted from my editor:

struct Entity {
    Id id;

    std::map<Id, void *> components;
};

template <typename T> void
add_component(Entity& e, T *c) {
    e.components[type_id<T>()] = c;
}

template <typename T> T *
get_component(Entity& e) {
    return static_cast<T *>(e.components[type_id<T>()]);
}

template <typename T> bool
has_component(Entity& e) {
    return (e.components[type_id<T>()] != nullptr);
}
 

A couple of notes regarding this implementation:
1. Id is just typedef'd as an int
2. type_id<> returns a unique Id (int) depending on which type was passed. It will always be consistent when the same type is passed though.

Basically I'm using an Entity-Component System where Entities are just a collection of components identified by a unique ID and components provide data. Systems act on entities with specific sets of components to manipulate them. Like an Entity with a TransformComponent and a RenderableComponent will be picked up by a RenderSystem and draw the entities.

So, to answer your question: get_component returns a pointer to the component of the type you requested so you can access it's data.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Address 0x10, or 0x00000010, is most likely a null pointer on which you try to access member at offset 0x10 (16). It's a fairly easy case for the debugger, so I can't believe it doesn't show you which pointer is null, and at which line of code (should be the top frame of the call stack) ???
Laurent Gomila - SFML developer

anthonyy

  • Newbie
  • *
  • Posts: 11
    • View Profile
    • Email
Hmm... I just tested and I can read and write any other members I want to. For example, I added an int to my Renderable struct and initialized it to 10 on "hero", then used get_component to change it's value. Maybe it is an SFML issue?  :-\

anthonyy

  • Newbie
  • *
  • Posts: 11
    • View Profile
    • Email
Okay I wiped SFML off my system again, built with debug symbols and the resulting call stack isn't much different.

sf::RenderTarget::draw(sf::RenderTarget * const this, const sf::Drawable & drawable, const sf::RenderStates & states

is the top of the stack. This function just calls

drawable.draw(*this, states);

I can't step into this call because it crashes immediately if I try  :(

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Then check all variables involved (even this), starting from the top frame of the stack, with your debugger. There must be something null.
Laurent Gomila - SFML developer

anthonyy

  • Newbie
  • *
  • Posts: 11
    • View Profile
    • Email
Honestly I can't find anything. "this" is not null. The sprite is not null. The sf::Drawable passed into the draw method casted to an sf::Sprite is not null and it's texture isn't either. The render component is not null. The transform component is not null.

Valgrind run with --track-origins=yes doesn't tell me where the error originates either.

I don't know what to do ;-;

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Then try to write a complete and minimal code that reproduces the problem, so that we can debug it on our side.
Laurent Gomila - SFML developer

anthonyy

  • Newbie
  • *
  • Posts: 11
    • View Profile
    • Email
This is as compact as I think I can get it.

#include <stdlib.h>

#include <map>
#include <string>

#include <SFML/Graphics.hpp>

typedef int Id;

/* This crap basically gets the unique ID for each component type */
Id
_unique_id() {
    static Id lastId = 0;
    return lastId++;
}

template<typename T>
Id type_id() {
    static Id typeId = _unique_id();
    return typeId;
}
/* ---------------------------------- */

/* Entity stuff */
/* ------------ */
struct Entity {
    Id id {0};

    std::map<Id, void *> components {};
};

template <typename T> void
add_component(Entity& e, T *c) {
    e.components[type_id<T>()] = c;
}

template <typename T> T *
get_component(Entity& e) {
    return static_cast<T *>(e.components[type_id<T>()]);
}
/* ------------ */

/* Util */
void
load_sprite(sf::Sprite& sprite, std::string file) {
    auto texture = (sf::Texture *)malloc(sizeof(sf::Texture));
    sprite.setTexture(*texture);
}
/* ---- */

struct RenderableComponent {
    sf::Sprite sprite;
};

int
main(int argc, char **argv) {
    sf::VideoMode videoMode {640, 480};
    sf::RenderWindow window {videoMode, "debug"};

    auto rc = (RenderableComponent *)malloc(sizeof(RenderableComponent));
    load_sprite(rc->sprite, "whatever.png");
    rc->sprite.setPosition(10, 30);

    Entity entity;
    add_component(entity, rc);

    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                window.close();
            }
        }

        window.clear();

        /* Try and use the sf::Sprite on RenderableComponent */
        window.draw(get_component<RenderableComponent>(entity)->sprite);
        /* aaaaaand it segfaults ;-; */

        window.display();
    }

    free(rc);
}
 

Thanks for helping out :)

 

anything