Ignorant
Ignorant

Reputation: 2681

Why std::vector::push_back segfaults with virtual destructor?

I have the following classes:

class Thing
{
public:

  Thing() {};
  virtual ~Thing() {}
};


class MyOwnThing : public Thing
{
public:

  std::vector<int> m;

  MyOwnThing() {};

  void init()
  {
    m.push_back(0);
    m.push_back(0);
    m.push_back(0);
    m.push_back(0);
    m.push_back(0);
    m.push_back(0);
    m.push_back(0);
    m.push_back(0);
    m.push_back(0);
    m.push_back(0);
    m.push_back(0);
    puts("done");
  }
};

Nothing unusual so far, except for the virtual destructor in the base class. Now, This is what I'm doing in the main function:

int main()
{
  MyOwnThing *t = (MyOwnThing *) new Thing(); // (1)
  t->init();
  delete t;
  return 0;
}

The code above generates a nice segfault on the 2nd call to push_back. Everything runs smoothly if I remove the virtual destructor from Thing. What's wrong?

1) I suspect that this cast might be the source of the problem.

Upvotes: 0

Views: 92

Answers (1)

Quentin
Quentin

Reputation: 63144

MyOwnThing *t = (MyOwnThing *) new Thing();

The need to cast should have been a red flag: a Thing is not a MyOwnThing. It doesn't even have an std::vector<int> for init() to act on.

Formally, you triggered UB as soon as you called that function from MyOwnThing on an object that isn't a MyOwnThing. The nonsensical fact that the behaviour changes with a virtual destructor is a symptom of everything breaking apart because you're treating some arbitrary memory section as a std::vector<int>.

Upvotes: 9

Related Questions