0

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.

Ignorant
  • 2,411
  • 4
  • 31
  • 48
  • 2
    The cast looks pretty suspicious IMO. I would use a `dynamic_cast` or `static_cast` for clarity (at least). It's also possible that the cast is performing a reinterpretation instead. – UnholySheep Dec 29 '16 at 14:44
  • 3
    You have a severe misunderstanding with regard to OO polymorphism as it is employed by C++. [Choose a good book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list), and get back to basics. – StoryTeller - Unslander Monica Dec 29 '16 at 14:53
  • 1
    Remove the cast in the code and fix it without the cast. As a general rule, every time you find yourself in need of a cast because there is a compiler error otherwise, you need to think 10 times before casting it. Chances are, you are doing something wrong. – SergeyA Dec 29 '16 at 15:11

1 Answers1

9
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>.

Quentin
  • 62,093
  • 7
  • 131
  • 191