dimanche 27 août 2017

SIGSEGV in destructor that I don't call myself?

I have this piece of code:

#include <vector>
using std::vector;

class Material {
public:
    virtual ~Material() {}
};

class DiffuseMaterial : public Material {
public:
    DiffuseMaterial() {}
};

class Sphere {
public:
    vector<Material*> materials = {};
    ~Sphere() { for (int i = 0; i < (int)materials.size(); ++i) delete materials[i]; }
    void addMaterial(Material* mat) { materials.push_back(mat); }
};

int main(int argc, char *argv[]) {
    vector<Sphere> models;
    models.push_back(Sphere());
    models[0].addMaterial(new DiffuseMaterial());
    models.push_back(Sphere());
    models[1].addMaterial(new DiffuseMaterial());

    return 0;
}

It seems that when I declare the models vector, a destructor is called. In this destructor, we try to call the destructor of the element type, which throws a SIGSEGV. Why is this happening?

Surprisingly, if I move the push_back(Sphere()) statements next to each other, and call addMaterial after them, it works fine. The SIGSEGV appears only when interleaving these calls.

Any idea why this happens?

Here is the gdb call stack. Frame #5 is the call to the vector destructor, and frame #0 is the call to the Sphere destructor.

#0  0x0000000000400cb5 in Sphere::~Sphere (this=0x617c80, __in_chrg=<optimized out>) at render2.cpp:17
#1  0x0000000000401e13 in std::_Destroy<Sphere> (__pointer=0x617c80) at /usr/include/c++/6.3.1/bits/stl_construct.h:93
#2  0x0000000000401a83 in std::_Destroy_aux<false>::__destroy<Sphere*> (__first=0x617c80, __last=0x617cb0) at /usr/include/c++/6.3.1/bits/stl_construct.h:103
#3  0x0000000000401694 in std::_Destroy<Sphere*> (__first=0x617c80, __last=0x617cb0) at /usr/include/c++/6.3.1/bits/stl_construct.h:126
#4  0x00000000004012b1 in std::_Destroy<Sphere*, Sphere> (__first=0x617c80, __last=0x617cb0) at /usr/include/c++/6.3.1/bits/stl_construct.h:151
#5  0x0000000000400e77 in std::vector<Sphere, std::allocator<Sphere> >::~vector (this=0x7fffffffda50, __in_chrg=<optimized out>) at /usr/include/c++/6.3.1/bits/stl_vector.h:426
#6  0x0000000000400b7b in main (argc=1, argv=0x7fffffffdba8) at render2.cpp:22

Aucun commentaire:

Enregistrer un commentaire