mardi 31 octobre 2017

std::vector emplace and underlying data get corrupted

I have some objects that I add them to a vector (vec1). Each object is dynamically created on the heap using new. And each object has a member (pointer) that points to the data in a different vector (vec2). The data must be created on the stack in vec2. I have problem setting the values of data through a pointer to obj, since it keeps crashing.

My strategy was to create data on the stack in vec2 using vec2.emplace_back() and set the pointer in obj through vec2.back() or vec2.data()+vec2.size(), as in the example below.

The code compiles was tested with clang and gcc. it crashes every time. What is going on?

class MyType
{
public:
    float* x;

public:
    MyType() { }
    MyType(const MyType& other) : x(other.x) { }
    MyType( MyType&& other) : x(other.x) {  }

    MyType& operator=(const MyType& other)
    {
        if(this!=&other)
            x = other.x;

        return *this;
    }

    MyType& operator=(MyType&& other)
    {
        if(this!=&other)
            x = std::move(other.x);

        return *this;
    }

    float data() const { return *x; }
    void setData(float dataX) { *x = dataX; }
};

void printObj(const MyType& obj)
{
    std::cout << "MyType x=" << obj.data() << std::endl;
}


int main (int argc, char const *argv[])
{
    std::size_t N = 10;

    std::vector<MyType*> vec1;
    std::vector<float> vec2;


    for(int i=0; i<N; i++)
    {
        MyType* ptr = new MyType;
        float* typePtr;

        vec2.emplace_back();
        typePtr = vec2.data()+vec2.size();

        ptr->x = typePtr;

        vec1.push_back(ptr);
    }

    for(int i=0; i<N; i++)
    {
        MyType* obj = vec1[i];
        obj->setData(1.0);

        printObj(*obj);
    }



    return 0;
}

The output of this:

MyType x=1
MyType x=1
MyType x=1
Segmentation fault: 11

Debugging it didnt prove successful, the problem:

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x13f800000)
    frame #0: 0x0000000100001e89 vector_emplace2`MyType::setData(this=0x0000000100100360, dataX=1) at vector_emplace_02.cpp:31
   28           }
   29       
   30           float data() const { return *x; }
-> 31           void setData(float dataX) { *x = dataX; }
   32       };
   33   
   34       void printObj(const MyType& obj)
Target 0: (vector_emplace2) stopped.   

Aucun commentaire:

Enregistrer un commentaire