Alexis
Alexis

Reputation: 27

_vfptr becomes null when I try to call a function

I am trying to Polymorphism in c++ but when I try to call a function , the _vfptr is equal to 0xcccccccccccccccc .

Here is the Object class who contain virtals functions :

class Object
{
public:

    Object()
    {
        Armageddon::Log::GetLogger()->trace("INSTANCIATE A NEW OBJECT");

    };

    virtual void InitVertexBuffer(ID3D11Device* device , ID3D11DeviceContext* device_contex ,Vertex v[], UINT VertexSize);
    virtual void InitIndexBuffer(ID3D11Device* device, ID3D11DeviceContext* device_contex, DWORD indices[], UINT IndicesSize);
    virtual void InitShaders(Microsoft::WRL::ComPtr <ID3D11Device>& device,std::wstring ShaderFloder, std::wstring VertexShader, std::wstring PixelShader, D3D11_INPUT_ELEMENT_DESC layout[], UINT SizeOfLayout);
    virtual void InitConstantBuffer(ID3D11Device* device, ID3D11DeviceContext* device_contex);


    virtual  void BindVertexBuffer(ID3D11DeviceContext* device_contex);
     virtual  void BindIndexBuffer(ID3D11DeviceContext* device_contex);
     virtual void BindShader(ID3D11DeviceContext* device_contex);
     virtual  void BindConstantBuffer(ID3D11DeviceContext* device_contex);
     virtual  void BindInputLayout(ID3D11DeviceContext* device_contex);
    // virtual void Draw(ID3D11DeviceContext* device_contex) = 0;
     virtual void Draw(ID3D11DeviceContext* device_contex);
     
     virtual  void DrawIndex(ID3D11DeviceContext* device_contex);
     virtual void UpDateConstantBuffer(Camera* cam);
     virtual void SetDrawFunction(const std::function<void(ID3D11DeviceContext* device_contex)>& callbackfunc) { DrawFunc = callbackfunc; };
     virtual void SetName(const char* n) { this->name = n; };
      const char* GetName() { return name; };
     virtual Object* GetInstance()
     {
         return this;
     };


    bool CustomDraw = false;
    int c = float(rand()) / float((RAND_MAX)) * 5.0f;
    int b = float(rand()) / float((RAND_MAX)) * 5.0f;
    float f = 0;
 private: 

    VertexBuffer<Vertex> VertexBuffer;
    IndexBuffer IndexBuffer;

    VertexShader vertexShader;
    PixelShader pixelShader;

    ConstantBuffer<CB_VS_SHADER> ConstantBuffer;
    // Object ID ? 
    const char*  name = "default name";
};

Here is the other class :

class  RenderModels : public Object
{
public:
    RenderModels(Microsoft::WRL::ComPtr <ID3D11Device> device, Microsoft::WRL::ComPtr <ID3D11DeviceContext> device_context) : device(device), device_context(device_context)
    {
        Armageddon::Log::GetLogger()->trace("STATRING LAODING MODEL");
    //  SetName("Model");
        Assimp::Importer imp;
        const aiScene* model = imp.ReadFile("..\\TestApplication\\assets\\Models\\suzanne.obj", aiProcess_Triangulate |
            aiProcess_JoinIdenticalVertices |
            aiProcess_ConvertToLeftHanded |
            aiProcess_GenNormals |
            aiProcess_CalcTangentSpace);



        //Assimp::Importer::GetErrorString();
    //  ProcessNode(model->mRootNode, model);
        const aiMesh* pMesh = model->mMeshes[0];
        Armageddon::Log::GetLogger()->trace(" LAODING MODEL : Enzo.obj");

        for (unsigned int i = 0; i < pMesh->mNumVertices; i++)
        {
            v.push_back({ pMesh->mVertices[i].x,pMesh->mVertices[i].y ,pMesh->mVertices[i].z,1.0f,0.0f,1,1,0 });
        }


        InitVertexBuffer(device.Get(), device_context.Get(), v.data(),v.size());

        //indices.reserve(pMesh->mNumFaces * 3);
        for (unsigned int i = 0; i < pMesh->mNumFaces; i++)
        {
            aiFace face = pMesh->mFaces[i];
            indices.push_back(face.mIndices[0]);
            indices.push_back(face.mIndices[1]);
            indices.push_back(face.mIndices[2]);
        }
        InitIndexBuffer(device.Get(), device_context.Get(),indices.data(), indices.size());











        D3D11_INPUT_ELEMENT_DESC layout[] =
        {
            {"POSITION",0,DXGI_FORMAT::DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D11_INPUT_CLASSIFICATION::D3D11_INPUT_PER_VERTEX_DATA,0},

            {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},
            {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},

        };
        InitShaders(device, L"..\\bin\\Debug-x64\\Armageddon\\", L"VertexShader.cso", L"PixelShader.cso", layout, ARRAYSIZE(layout));

        InitConstantBuffer(device.Get(), device_context.Get());
        CustomDraw = true;
        Armageddon::Log::GetLogger()->error("FINISHED INIT RENDERMODEL");

    };
    

    void ProcessNode(aiNode* node, const aiScene* scene)
    {
        //Armageddon::Log::GetLogger()->trace("PROCESS NODE");

        for (UINT i = 0; i < node->mNumMeshes; i++)
        {
            aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
            modelMeshes.push_back(ProcessMesh(mesh, scene));
        }
        for (UINT i = 0; i < node->mNumChildren; i++)
        {
            this->ProcessNode(node->mChildren[i], scene);
        }
    //  Armageddon::Log::GetLogger()->trace("VECTOR ADRESS :  {0}",modelMeshes.get_allocator().address(modelMeshes[0]));
    };

    Mesh ProcessMesh(aiMesh* mesh, const aiScene* scene)
    {
        std::vector<Vertex> v;
        std::vector<DWORD> indices;
        for (unsigned int i = 0; i < mesh->mNumVertices; i++)
        {
            if (mesh->mTextureCoords[0])
            {
                v.push_back({ mesh->mVertices[i].x,mesh->mVertices[i].y ,mesh->mVertices[i].z,mesh->mTextureCoords[0][i].x,mesh->mTextureCoords[0][i].y,1,1,0 });
            }
        }
        for (unsigned int i = 0; i < mesh->mNumFaces; i++)
        {
            aiFace face = mesh->mFaces[i];
            for (UINT j = 0; j < face.mNumIndices; j++)
            {
                indices.push_back(face.mIndices[j]);
            }

        }
        
        return Mesh(device.Get(), device_context.Get(), v, indices);
    };

    /*Object* GetInstance() override
    {
        Armageddon::Log::GetLogger()->trace("INSTANCE");
        return this;
    };*/

    /*virtual void Draw(ID3D11DeviceContext* device_contex) 
    {
        Armageddon::Log::GetLogger()->trace("d");
    };*/

    std::vector<Mesh> GetMeshArray()
    {
        return this->modelMeshes;
    };
private:
    std::vector<Vertex> v;
    std::vector<DWORD> indices;

    std::vector<Mesh> modelMeshes;
    Microsoft::WRL::ComPtr <ID3D11Device>& device;
    Microsoft::WRL::ComPtr <ID3D11DeviceContext>& device_context;
};

And finally here is where I instanciate the Object :

class TestApp : public Armageddon::Application
{
public:

     void OnUpdate() override;
     void OnRender() override;
     void ImGuiRender() override;
     void Init() override;
    
     void onMouseEvent(MouseEvent::MEventType);


     void CameraControls();
    TestApp()
    {
    
    }

    ~TestApp()
    {
    }
private:
    ImVec2 CurrentWindowSize;
    std::vector<Object*> o;   

};



void TestApp::Init()
{
    

    RenderModels m(Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetComptrDevice(), Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetComptrDeviceContext());
    o.push_back(&m); // HERE IS WHERE I PUT THE RENDERMODEL OBJECT 

    Armageddon::Log::GetLogger()->trace("NAME : {0}", o[0]->GetName());
    

    //Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetVectorObjects()->at(0).get().GetInstance()->GetName(); //HERE EVERYTHING IS FINE NO PROBLEM WITH _VFPTR
    a++;
}

This is the function where all fails:

void TestApp::OnRender()
{

    
    for (UINT i = 0; i < o.size(); i++)
    {

        
        o[i]->Draw(Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->Getdevicecontext()); // HERE ALL FAIL
    }
}

I have used the Visual studio debugger to visualize the problem :

you can see in the second pictures the values of c and b changes and the _vfptr is null Everything is fine

error

Upvotes: 0

Views: 343

Answers (1)

StPiere
StPiere

Reputation: 4243

The problem is in TestApp::Init

o.push_back(&m); // HERE IS WHERE I PUT THE RENDERMODEL OBJECT 

You are pushing address of local object into the vector.

At the end of TestApp::Init() scope, m is destroyed and you're ending with a pointer to an invalid address.

You can try storing smart pointers (shared_ptr or unique_ptr). For example:

auto m = make_unique<RenderModels>(Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetComptrDevice(), Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetComptrDeviceContext())

or

auto m = make_shared<RenderModels>(Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetComptrDevice(), Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetComptrDeviceContext())

...

std::vector<std::unique_ptr<Object>> o;  // or shared_ptr if you need shared ownersheep

and then

o.push_back(std::move(m)); // or o.push_back(m) if shared_ptr

Upvotes: 4

Related Questions