0

I have those inheritance classes : Base Class: Entity

Derived from Entity Classes: Actor, Obj, Enemy

The Base class Entity contains an obj of a user-defined-type that i called "CollisionStuff". When i run my program the destructor of CollisionStuff is called after every CollisionStuff constructor call and every time game-loop goes on.

so my call is: why is this happening?

As you can see below, i allocate dinamically some arrays in the setRectangle method, the programm calls the destructor, it deletes my data and when i try to use them... it calls "_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));".

Thank you in before

here my code: Entity.h

enum e_Type {tActor = 0, tObj, tEnemy, tBackg};

class Entity
{
public:
    Entity(void);
    ~Entity(void);

    float getH();
    float getW();
    void setWH(float W, float H);
    bool CreateSprite(std::string path);
    sf::Sprite& getSprite();
    void setType(e_Type type);
    e_Type getType();
    CollisionStuff getColStuff();

    static std::list<Entity*> List;

protected:
    sf::Sprite m_sprite;
    sf::Texture m_texture;
    float m_h;
    float m_w;
    e_Type m_type;
    CollisionStuff m_colStuff;

    void addToList();
};

CollisionStuff.h

class CollisionStuff
{
public:
    CollisionStuff();
    ~CollisionStuff(void);

    void setRectangle(int  W, int H);
    void followTheSprite(Entity entity);

private:
    sf::Vector2f* m_a;
    sf::Vector2f* m_b;
    sf::Vector2f* m_c;
    sf::Vector2f* m_d;
    /* this member data are sides of rectangle used
    to manage collisions between object throughout the scenario 

            a
      -------------
      |           |
    c |           | d
      |           |
      -------------
            b
    */

};

CollisionStuff.cpp

CollisionStuff::CollisionStuff()
{
    //setRectangle(0, 0);
}

void CollisionStuff::setRectangle(int W, int H)
{
    m_a = new sf::Vector2f[W];
    m_b = new sf::Vector2f[W];
    m_c = new sf::Vector2f[H];
    m_d = new sf::Vector2f[H];
}

void CollisionStuff::followTheSprite(Entity entity)
{
    entity.getSprite().setOrigin(0, 0);
    sf::Vector2f UpLeftVertex = entity.getSprite().getPosition();


    for(int i = 0; i <  entity.getW(); i++)
    {
        m_a[i].x = UpLeftVertex.x + i;
        m_a[i].y = UpLeftVertex.y;

        m_b[i].x = UpLeftVertex.x + i;
        m_b[i].y = UpLeftVertex.y + entity.getH();
    }

    for(int i = 0; i <  entity.getH(); i++)
    {
        m_c[i].x = UpLeftVertex.x;
        m_c[i].y = UpLeftVertex.y + i;

        m_d[i].x = UpLeftVertex.x + entity.getW();
        m_d[i].y = UpLeftVertex.y + i;
    }

}



CollisionStuff::~CollisionStuff(void)
{
    delete [] m_a;
    delete [] m_b;
    delete [] m_c;
    delete [] m_d;
}

EDIT Thank you for the answers. Example of CollisionStuff use

Actor.cpp (it's a derived class of Entity)

Actor::Actor(void)
{
    if(!CreateSprite("D://Sprites//MainChar.png"))
    {
        std::cout << "Impossibile creare sprite" << std::endl;
    }
    else
    {
        std::cout << "Creazione sprite riuscita" << std::endl;  
        m_sprite.setPosition(100.0f, 365.0f);
        m_sprite.setOrigin(20, 35);
        //m_sprite.setPosition(190.0f, 382.5f); // 200, 400
        setWH(40, 70);
        m_health = 100;
        m_status = Good;
        setType(tActor);
        m_jCounter = -1;
        m_action = Null;

        setColStuff();
    }
}

void Actor::setColStuff()
{
    m_colStuff.setRectangle(m_w, m_h);
}



void Actor::physic()
{
    //setColStuff();
    m_colStuff.followTheSprite(*this);
}

main.cpp

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

    std::list<Entity*>::iterator i;

    Background BG;
    Level1 FirstLev;
    Actor Doodle; 

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

            Doodle.inputEvts();
        }

        Doodle.act(Doodle.getAction());

        Doodle.physic();

        window.clear();

        window.draw(BG.getSprite());
        window.draw(Doodle.getSprite());

        FirstLev.drawLevel(window);

        window.display();
    }
    return 0;
}
Pepp94
  • 11
  • 3
  • You haven't posted the relevant code (the bit *using* `CollisionStuff`) but I'd guess you're in a situation where `CollisionStuff` is constructed, copied (copy constructed or assigned), and then the first one destroyed. You should change the line which creates it, or look into C++11's move semantics. – Dave Aug 24 '13 at 14:57
  • Are you saying the assert fails? Because that would likely have to do with you using something after it was deleted. – Floris Velleman Aug 24 '13 at 14:59
  • Incidentally, you've violated the rule of 3 for using pointers in a class, so this code will be error-prone. – Dave Aug 24 '13 at 14:59
  • `CollisionStuff` breaks the [Rule of Three](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three), so copying it will cause the type of calamity you describe. – Mike Seymour Aug 24 '13 at 15:02
  • Where is the definition for the `Entity` desstructor? The class says there is one. – Thomas Matthews Aug 24 '13 at 19:57
  • If `CollisionStuff:setRectangle()` is never called, the destructor will delete memory that was never allocated. – Thomas Matthews Aug 24 '13 at 19:59

1 Answers1

2

It's really hard to tell from the bit of code that you posted, but if I had to guess I'd say it's probably related to this:

CollisionStuff getColStuff();

you're returning CollisionStuff by value, which means a new copy will be created by whoever is calling this. It'll have the same pointers that the original CollisionStuff object allocated, and it'll delete them when it goes out of scope, leaving the original one with dangling pointers.

You can try returning by reference or by pointer, but either way you should write a copy constructor and override the assignment operator for CollisionStuff (Rule of Three).

Another idea would be to use std::vector<sf::Vector2f> instead of allocating the sf::Vector2f array yourself.

filipe
  • 3,370
  • 1
  • 16
  • 22
  • The error occurs exactly when "FollowTheSprite" is called, because dynamic allocated variables doesn't exist anymore. Anyway i'll read "Rule of Three" you just linked. Thanks – Pepp94 Aug 24 '13 at 15:11