1

my problem is that when I want to divide the code into smaller functions it throws me a runtime error: access violation.

Error dialog image

Since everything is passed by value I have no idea why such an error would occur. There is nothing to do about memory.

General code:

                                // main.cpp
#include "stdafx.h"

#include "SFML/Graphics.hpp"
#include "GameEngine.h"

int main()
{
    sf::RenderWindow* window = new sf::RenderWindow(sf::VideoMode(200, 200), "SFML works!");

    GameEngine game(window);
    game.run();

    delete window;
    return 0;
}

                                // DrawableVertices.h
#pragma once
#include "SFML\Graphics.hpp"
using namespace sf;

class DrawableVertices : public Drawable, public Transformable
{
    VertexArray vertices;
    Texture* pTexture;

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

    DrawableVertices(VertexArray vertices, Texture* pTexture = nullptr);
    DrawableVertices();

    Texture* getTexture();
    VertexArray* getVertices();
};




                                // DrawableVertices.cpp
#include "stdafx.h"
#include "DrawableVertices.h"

DrawableVertices::DrawableVertices(sf::VertexArray _vertices, sf::Texture* _pTexture)
{
    vertices = _vertices;
    pTexture = pTexture;
}

DrawableVertices::DrawableVertices()
{
    vertices = sf::VertexArray(sf::Points, 1);
    pTexture = nullptr;
}

void DrawableVertices::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
    states.transform *= getTransform();
    states.texture = pTexture;
    target.draw(vertices, states);
}

sf::Texture* DrawableVertices::getTexture() { return pTexture; }
sf::VertexArray* DrawableVertices::getVertices() { return &vertices; }

Working code (all in one function):

                                //GameEngine.h
#pragma once
#include "DrawableVertices.h"

class GameEngine
{
    RenderWindow* pWindow;

public:
    GameEngine(RenderWindow* window);
    void run();
};

                                //GameEngine.cpp
#include "stdafx.h"
#include "GameEngine.h"

GameEngine::GameEngine(RenderWindow* window)
{
    pWindow = window;
}

void GameEngine::run()
{
    const int X_DIFF = 8;
    const int PLAYER_Y = 24;
    const int PLAYER_X = 48;

    VertexArray playerShape(TrianglesStrip, 4);
    playerShape[0].position = Vector2f(X_DIFF, 0);
    playerShape[0].color = Color(0, 127, 255);

    playerShape[1].position = Vector2f(PLAYER_X - X_DIFF, 0);
    playerShape[1].color = Color(0, 127, 255);

    playerShape[2].position = Vector2f(0, PLAYER_Y);
    playerShape[2].color = Color(0, 0, 255);

    playerShape[3].position = Vector2f(PLAYER_X, PLAYER_Y);
    playerShape[3].color = Color(0, 0, 255);

    DrawableVertices player(playerShape);
    player.setOrigin(PLAYER_X / 2, PLAYER_Y / 2);
    player.setPosition(64, 64);

    while (pWindow->isOpen())
    {
        Event event;
        while (pWindow->pollEvent(event))
        {
            if (event.type == Event::Closed)
                pWindow->close();
        }

        pWindow->clear();
        pWindow->draw(player);
        pWindow->display();
    }

}

Not working code, throwing access violation while drawing player [ pWindow->draw(player) line ]

                                //GameEngine.h
#pragma once
#include "DrawableVertices.h"

class GameEngine
{
    RenderWindow* pWindow;
    DrawableVertices player;

    void createPlayer();

public:
    GameEngine(RenderWindow* window);
    void run();
};

                                // GameEngine.cpp
#include "stdafx.h"
#include "GameEngine.h"


GameEngine::GameEngine(RenderWindow* window)
{
    pWindow = window;
    createPlayer();
}

void GameEngine::createPlayer()
{
    const int X_DIFF = 8;
    const int PLAYER_Y = 24;
    const int PLAYER_X = 48;

    VertexArray playerShape(TrianglesStrip, 4);
    playerShape[0].position = Vector2f(X_DIFF, 0);
    playerShape[0].color = Color(0, 127, 255);

    playerShape[1].position = Vector2f(PLAYER_X - X_DIFF, 0);
    playerShape[1].color = Color(0, 127, 255);

    playerShape[2].position = Vector2f(0, PLAYER_Y);
    playerShape[2].color = Color(0, 0, 255);

    playerShape[3].position = Vector2f(PLAYER_X, PLAYER_Y);
    playerShape[3].color = Color(0, 0, 255);

    player = DrawableVertices(playerShape);
    player.setOrigin(PLAYER_X / 2, PLAYER_Y / 2);
    player.setPosition(64, 64);
}


void GameEngine::run()
{

    while (pWindow->isOpen())
    {
        Event event;
        while (pWindow->pollEvent(event))
        {
            if (event.type == Event::Closed)
                pWindow->close();
        }

        pWindow->clear();
        pWindow->draw(player);
        pWindow->display();
    }

}

What's worse when I display all player's information like position etc. inside run() method it shows the proper result. It means that player is initialised properly and it exists like it is supposed to.

Sorry for a lot of code, but wanted to show everything that could be useful. Obviously my whole code is bigger, I just put the part making problems into a separate project.

// Edit

Yeah, debugger says that pTexture member of player has a bad pointer.

image from debugging working and not working code

I suppose that overloading = operator might fix the problem. However, I want to understand how it works that this code works without any problems:

void GameEngine::run()
{
    DrawableVertices player = DrawableVertices(playerShape);
    // ...
    pWindow->draw(player);
}

And packing it into a fuction doesn't:

void GameEngine::createPlayer()
{
     // ...
     DrawableVertices player = DrawableVertices(playerShape);
}

void GameEngine::run()
{
    createPlayer();
    // ...
    pWindow->draw(player);
}
Grzyboo
  • 35
  • 6
  • 1
    What does the debugger tell you when you step through the code? – Ken White May 11 '16 at 01:19
  • What do you mean by what does the debugger tell? The debugger output says exactly what screenshot says: "Exception thrown at 0x0FBA8BC6 (sfml-graphics-d-2.dll) in AccessViolationBug.exe: 0xC0000005: Access violation reading location 0xCCCCCCE4." Going to "Locals", the player looks valid. – Grzyboo May 11 '16 at 01:31
  • (Sorry, I missed the image because you did such a poor job with the alt text that it's almost invisible.) Step through the code to the line before the AV occurs, and examine your variables there. Something isn't correct, or the AV wouldn't be happening. I doubt the error is in sfml, which means something in your code is causing the issue that isn't being noticed before the call into the DLL. Stack corruption, an invalid pointer, a memory overwrite, or something similar to that will most likely be the cause. You're in a better position to find it than we are, because you have all the pieces. – Ken White May 11 '16 at 01:43
  • 1
    That image is not *stepping through the code in a debugger*. It's the exception dialog that happens **after** the AV is caused. You need to **use the debugger** to step through the code **before** the AV to see what's causing it. – Ken White May 11 '16 at 01:46
  • Possible duplicate of [How to end up with a pointer to 0xCCCCCCCC](http://stackoverflow.com/questions/3618572/how-to-end-up-with-a-pointer-to-0xcccccccc) – nobody May 11 '16 at 02:06
  • No, it doesn't answer why the exact same code doesn't work when thrown into a separate function. @Ken White thanks for the advice, now I know what is corrupt, but still don't know why (edited the main post) – Grzyboo May 11 '16 at 10:17
  • You _still_ need to run your code through a debugger. – Lightness Races in Orbit May 11 '16 at 10:28
  • @LightnessRacesinOrbit What do you mean by that? I set a breakpoint and observed variables. I know that pTexture is causing the problem. Now my problem is why assigning a local object to a class member one doesn't copy a null pointer and instead assigns 0xcccccccc – Grzyboo May 11 '16 at 10:34
  • maybe you should `return` after `pWindow->close()`, instead of going on to work on the window? – M.M May 11 '16 at 23:43

1 Answers1

1

The error (if I'm not wrong) is very simple

In this constructor

DrawableVertices::DrawableVertices(sf::VertexArray _vertices, sf::Texture* _pTexture)
{
    vertices = _vertices;
    pTexture = pTexture;
}

you copy pTexture on itself; so pTexture start undefined and remain undefined.

I suppose that your intention was

DrawableVertices::DrawableVertices(sf::VertexArray _vertices, sf::Texture* _pTexture)
{
    vertices = _vertices;
    pTexture = _pTexture; // _pTexture !
}

p.s.: sorry for my bad English.

max66
  • 65,235
  • 10
  • 71
  • 111
  • Holy moly, you've got an eagle eye. How didn't I see it! Thanks a lot :) The fact that it did work properly in some cases completely mislead me so I wouldn't ever suspect a thing like misspelling. – Grzyboo May 11 '16 at 13:38
  • You're welcome. Isn't eagle eye: it's experience. I've done so many errors in my (C/C++ programmers) life that, if you do an error, almost certainly I've done it before. :-( – max66 May 11 '16 at 13:44
  • I see, sometimes this language is pure pain :P – Grzyboo May 11 '16 at 16:53
  • 1
    @GrzybooX using ctor-initialization instead of assignment makes it less likely for this problem to occur – M.M May 11 '16 at 23:49