简体   繁体   中英

push_back crashed when using std::vector if the type only defined copy constructor with c++11

The code like this:

#include <iostream>
#include <vector>

struct Foo
{
    int i;
    double d;
};

class Boo
{
public:
    Boo() : fptr(nullptr) 
    {
        std::cout << "Boo default construct..." << std::endl;
    }
    Boo(int i, double d):fptr(new Foo{i,d})
    {
    }

    Boo(const Boo &rhs) :fptr(new Foo{rhs.fptr->i,rhs.fptr->d})
    {
    }

    Foo *fptr;
};

int main(int argc, char const *argv[])
{
    std::vector<Boo> vec(1);
    Boo b(42, 10.24);
    vec.push_back(b);
    return 0;
}

Env: Ubuntu 16.4 LTS with gcc 5.4 g++ -std=c++11 test.cpp -o test -g

./test

If define move constructor,this will work good. I debuged it several hours but can not found what's wrong with it, maybe because some rules in c++ 11 that i did't know.

Could somebody help me? Thanks!

Your Boo copy constructor derefernces a pointer fptr that may be null.

A std::vector::push_back may reallocate vector storage. Reallocating may use copy constructors.

That is what is happening in your program. You are copying a Boo that has a null pointer.

The problem is that in the copy constructor of Boo you're dereferencing a nullptr . This is because when you wrote:

std::vector<Boo> vec(1); //this creates a vector of size 1 using Boo's default constrcutor

This is what happens due to the above statement:

  1. The above statement creates a vector named vec of size 1 using Boo 's default constructor .
  2. This means that there is already 1 Boo object inside vec . Moreover since this Boo object was created using the default constructor, its fptr is set to nullptr .

Now, when you wrote:

vec.push_back(b);// this adds/push_back object b onto the vector vec so that now its size will be 2

Now, these are the important things that you have to remember here:

  1. The vector has already 1 Boo object inside it which has its fptr as nullptr .
  2. Now you're adding one more element into the vector, reallocation may happen. And if/when this reallocation happens, the copy constructor of Boo will be used.
  3. And when this copy constructor is used to copy the already present Boo object, it dereferences its fptr . But since that fptr is nullptr and we know that dereferencing a nullptr is undefined behavior , so this may cause the program to segmentation fault as in your case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM