Search code examples
c++segmentation-faultentity-component-system

Segmentation fault when calling virtual function in C++


I am currently working on an ECS in C++ for my game engine. I have a base system struct that has two virtual functions init() and update() which are implemented in derived structs. I have an addSystem() and removeSystem() functions which use templates and I have an array of System* systems. If I try to call them it gives me a segmentation fault.

System:

struct System{
public:
    uint32_t id;
    virtual void init(World* world){}
    virtual void update(World* world){}
};

addSystem():

template<typename T>
    void addSystem(){
        T* system = allocate<T>();
        system->id = getID();
        systems.append(system);
        #ifdef DEBUG
                LOG("ECS: System added successfully.");
        #endif // DEBUG
}

removeSystem():

template<typename T>
    void removeSystem(uint32_t id){
        unsigned int index;
        for(int i = 0; i < systems.size; i++){
            if (systems[i]->id == id){
                index = i;
                break;
            }
        }

        systems.remove(index);
}

Call to virtual function from System*:

for (int i = 0; i < systems.size; i++){
    systems[i]->init(this); // Here is the segmentation fault.
}

for (int i = 0; i < systems.size; i++){
    systems[i]->update(this); // Here is the segmentation fault.
}

Please ask if more info is needed.

Edit: size is equal to 1 in the for loop and systems[i] is a valid pointer. I also tested p systems[i]->update and it also has a valid address. The problem is while calling it.


Solution

  • #ifndef SYSTEMTEST_H_
    #define SYSTEMTEST_H_
    
    #include <stdint.h> 
    #include <vector>
    #include <iostream>
    
    struct World
    {
        int id;
    };
    
    struct System{
    public:
        uint32_t id;
        virtual void init(World* world){}
        virtual void update(World* world){}
    };
    
    int systemID = 0;
    std::vector<System*> systems;
    
    
    struct Derived : System
    {
        void init(World* world){
            std::cout << "init" << std::endl;
        }
        void update(World* world){
            std::cout << "update" << std::endl;
        }
    };
    
    uint32_t getID()
    {
        return systemID++;
    }
    
    template<typename T> void addSystem(){
        T* system = new T();
        system->id = getID();
        //systems.append(system);
        systems.push_back(system);
    }
    
    template<typename T> void removeSystem(uint32_t id){
        unsigned int index;
        for (int i = 0; i < systems.size; i++){
            if (systems[i]->id == id){
                index = i;
                break;
            }
        }
        //remove operator
        //systems.remove(index);
    }
    #endif
    
    #include <iostream>
    #include "SystemTest.h"
    using namespace std;
    
    int main(int argc, char** argv){
    
        addSystem<Derived>();
        for (int i = 0; i < systems.size(); i++)
        {
            World *world;
            world = new World;
            systems[i]->init(world);
        }
        return 0;
    
    }
    

    I understand your description.

    I try to complete the rest

    Run was successful