Почему я получаю ошибку SIGSEGV при использовании функции класса из указателя?

Я новичок в С++ и столкнулся с первой проблемой. У меня есть класс GameObject, в котором мне нужно каким-то образом хранить множество компонентов. Каждый компонент представляет собой отдельный класс, поэтому я не могу просто использовать вектор. Я решил сохранить тип компонента и указатель на этот объект. Проблема в том, что когда я получаю, возвращаю этот компонент и использую функцию класса, которая использует его переменные-члены, я получаю ошибку SIGSEGV (да, звучит запутанно). Однако, если я обычно использую этот класс и эту функцию, я не получаю ошибку SIGSEGV.

GameObject.h:

enum ComponentType
{
    MeshComponent // currently only one type
};

struct Component
{
    ComponentType type;
    void *pointer;
};
class GameObject
{
    private:
    std::vector<Component> components;
    public:
    void addComponent(ComponentType type);
    template<typename T> T* getComponent()
    {
        for(std::vector<Component>::size_type i = 0; i != components.size(); i++)
        {
            // will need to somehow check T type later
            if(components[i].type == MeshComponent)
            {
                return (Mesh*)&components[i].pointer;
            }
        }
        Debug::Loge(GAMEOBJECT_TAG, "No %s component in %s gameobject!", componentTypeToString(MeshComponent).c_str(), name.c_str());
        return 0;
    }
}

GameObject.cpp:

void GameObject::addComponent(ComponentType type)
{
    Component component;
    component.type = type;
    if(type == MeshComponent)
    {
        Mesh *mesh = new Mesh();
        component.pointer = &mesh;
    }
    components.push_back(component);
}

Mesh.h

class Mesh
{
    public:
    Mesh *setMeshData(std::vector<GLfloat> data);
};

Mesh.cpp

Mesh *Mesh::setMeshData(vector<GLfloat> data)
{
    meshData = data;
    return this;
}

И, наконец, вот как я его использую:

GameObject object;
void somefunction()
{
    object.addComponent(MeshComponent);
    object.getComponent<Mesh>()->setMeshData(triangle_data); // SIGSEGV HERE!!
    // if I use this one instead above - no sigsegv, everything is fine.
    Mesh mesh;
    mesh.setMeshData(triangle_data);
}

person Gintas_    schedule 20.08.2013    source источник
comment
return (Mesh*)&components[i].pointer; Быстрый просмотр - похоже, вы получаете нужный указатель (.pointer), затем берете адрес указателя и возвращаете его.   -  person BoBTFish    schedule 20.08.2013
comment
Вы должны как минимум проверить, что object.getComponent<Mesh>() не возвращает 0.   -  person juanchopanza    schedule 20.08.2013
comment
std::vector‹std::unique‹Component›› может облегчить жизнь, если у вас есть C++11.   -  person doctorlove    schedule 20.08.2013


Ответы (2)


Здесь

    Mesh *mesh = new Mesh();
    component.pointer = &mesh;

вы берете адрес указателя на mesh. Вместо этого попробуйте

    Mesh *mesh = new Mesh();
    component.pointer = mesh;

потому что вы определили свой Component-указатель как void* pointer. Если бы вы хотели взять адрес Mesh*, вам пришлось бы использовать void** pointer, но это глупо и привело бы к еще одному SIGSEGV.

person bash.d    schedule 20.08.2013
comment
Также return (Mesh*)&components[i].pointer это такая же проблема. - person Nbr44; 20.08.2013

if(components[i].type == MeshComponent)
{
     return (Mesh*)&components[i].pointer;
}

Ваш возвращаемый тип — Mesh*, но &components[i].pointer будет недействительным**. + объяснение выше от @bas.d

person Krishan Subudhi    schedule 20.08.2013