please skip the explanation if you know how the entity component architecture works!

Explanation:

Okay so I'm trying to create an entity component system, and i'm stuck at a very strange problem, that has never occurred until now, basically i have an Entity class which contains some variables(like name, tag, id), and a pointer vector which keeps track of all the components that get added to the entity, that's the entity class, all the components derive from the Component class, which has a type(char*), and virtual functions such as Start, Update, etc.This is how you create a component:

#pragma once
class printcomponent : public Component {
  printcomponent() : Component("printcomponent"){} // the printcomponent constructor derives from the component constructor which takes a char* as parameter, and sets the component's type to that char*
 void Start(){
 cout << "This is printed on start" << endl;
} 
void Update(){
 cout << "This gets printed every frame" << endl;
}
 ~printcomponent();//destructor
}

My Problem:

Okay so my problem occurs only when i try to get the component of type Rigidbody2d, this is "PhysicalObject.cpp", physicalobject is a type of entity which already has some components, like a prefab, so i don't have to always add the same components to an entity type, like a physical object:

#include "stdafx.h"
#include "Public.h" // all the public variables are in here, and declared in Public.cpp
#include "PhysicalObject.h"

PhysicalObject::PhysicalObject(float boxwidth, float boxheight, float gscale, bool fixedr, float nDnsity, float nFricton, string name, string tag, bool isactive, bool isstatic) : Entity(name, tag, isactive, isstatic) // so basically the constructor creates an entity
{
    this->AddComponent<Transfrm>(b2Vec2(0.f, 0.f), 0.f, b2Vec2(1.f, 1.f)); // i add a transform component
    this->AddComponent<RigidBody2D>(gscale, fixedr); // i add a rigidbody2d component, there is no problem when adding components
    this->AddComponent<SprtRend>(this); // again spriterenderer component
    trans = this->GetComponent<Transfrm>(); // okay so i have 2 variables for easily accessing specific components, i have one trans for transform, and one rigidb for rigidbody2d, basically calling this instead of getting component is much more efficient !
    rigidb = this->GetComponent<RigidBody2D>(); // this is the line causing me problems, the previous line doesn't cause any problem, but this causes an  Unhandled exception, in the function GetComponent of Entity.h
}

the error points to "entity.h" getcomponent function Entity.h:

// add component, constructor, and other functions.

template <typename T>
T* GetComponent() {
    T t; // so basically this function creates a new given type T and loops through all the components until it finds a matching type
    for (unsigned i = 0; i < AllComponents.size(); i++) {
        if (AllComponents.at(i)->Type == t.Type) { // when debugging in this line, in the 'autos' window, it shows the type as "RigidBody2D", which is fine, but after i continue to the other line, it gives me the unhandled exception and the type of 't' is something like: "/x" and some numbers, which makes no sense, and doesn't occur when getting other components.
            return dynamic_cast<T*>(AllComponents.at(i));
            break;
        }
    }
    cout << "Entity: " << Name << " Does Not Have Component of Type: " << t.Type << endl;
}

// desctructor

and finally the RigidBody2d.h file, which contains the rigidbody component, which is no different than other components, but still gives an error.

RigidBody2D.h: // I'm going to show all the code, because i'm not sure what might be causing the problem, so i apologize if this post becomes extremely long, also note that i've implemented the box2d library in my engine so there is some variables and functions from that, which i don't think are causing any error.

#pragma once
#include "Component.h"
#include "Transfrm.h" // i need the transform component for the rigidbody because it contains a position, rotation, etc.        

class RigidBody2D : public Component
{
public:
    b2BodyDef bodyDef;
    Transfrm* Trans;
    b2Body* Body;
    float* GScale; // this pointer needs to point to the gravity scale variable of body
    bool* FreezeRot; // this pointer needs to point to the freeze rotation variable of body
    bool IsKinematic;

    void SetGScale(float newgs){
        *GScale = newgs;
    }
    void SetFreezeRot(bool newfr) {
        *FreezeRot = newfr;
    }
    void SetIsKinetic(bool newisk) {
        IsKinematic = newisk;
    }
    RigidBody2D(float gscale = 1.f, bool fixedr = false); // constructor, before i used 2 constructors one with no parameters, but that caused me errors, because the compilier didn't know which constructor to use since they were the same(didn't require parameters)
    ~RigidBody2D();
};

and finally RigidBody2D.cpp:

#include "stdafx.h"
#include "Public.h"
#include "RigidBody2D.h"

RigidBody2D::RigidBody2D(float gscale, bool fixedr) : Component("RigidBody2D")
{
    Trans = new Transfrm(b2Vec2(0.f, 0.f), 0.f, b2Vec2(1.f, 1.f));
    bodyDef.type = b2_dynamicBody;
    bodyDef.position.Set(Trans->Position.x, Trans->Position.y);
    bodyDef.gravityScale = gscale;
    bodyDef.fixedRotation = fixedr;
    GScale = &bodyDef.gravityScale;
    FreezeRot = &bodyDef.fixedRotation;
    Body = CurrentPhysicsWorld->CreateBody(&bodyDef);
}
RigidBody2D::~RigidBody2D() {
    delete Trans;
    delete GScale;
    delete FreezeRot;
    CurrentPhysicsWorld->DestroyBody(Body);
};

I'm extremely sorry for the gigantic post, which took me like 2 hours to write, but I've been searching and debugging like 3 days, and still can't find a solution, because i have never encountered such problem, thanks in advance.

3

There are 3 answers

2
Support Ukraine On BEST ANSWER

To me this part looks strange:

RigidBody2D::RigidBody2D(float gscale, bool fixedr) : Component("RigidBody2D")
                               ^^^^^^^ gscale is a float
{
    Trans = new Transfrm(b2Vec2(0.f, 0.f), 0.f, b2Vec2(1.f, 1.f));
    bodyDef.type = b2_dynamicBody;
    bodyDef.position.Set(Trans->Position.x, Trans->Position.y);
    bodyDef.gravityScale = gscale;
                           ^^^^
                           Used for initialization of bodyDef.gravityScale 

    bodyDef.fixedRotation = fixedr;
    GScale = &bodyDef.gravityScale;
    ^^^^^^
    Pointer to bodyDef.gravityScale

    FreezeRot = &bodyDef.fixedRotation;
    Body = CurrentPhysicsWorld->CreateBody(&bodyDef);
}
RigidBody2D::~RigidBody2D() {
    delete Trans;
    delete GScale;
    ^^^^^^^^
    Delete of bodyDef member which wasn't created by new        



    delete FreezeRot;
    CurrentPhysicsWorld->DestroyBody(Body);
};

So it looks to me that you are trying to delete something that wasn't created by new

0
molbdnilo On

A couple of things that stand out:

GetComponent doesn't always return anything, which easily leads to undefined behaviour.

In ~RigidBody2D(), you're deleteing two objects – GScale and FreezeRot – which were not created using new, but are owned by bodyDef.
This is, of course, undefined.

Whether these two are enough to solve your problems is hard to guess.
Based on the code you posted, I suspect there's probably many other similar issues to hunt down.

2
diametralpitch On

I think the problem is how you are manually deleting GScale and FreezeRot. In the GetComponent you create a temporary object T which will go out of scope at the end of the function. If you search for a RigidBody type, it's destructor will be called when the function finishes, deleting some pointers which should be left for Box2D to manage.

As a fix, I would suggest removing the code hat deletes these 2 members, and for each type, creating a static member called Type so you can do:

T::Type

instead of having to create a temporary object:

T t;
T.type