4

I have this code who gives me a segmentation fault 3 or more elements. I tested on vs and clang and works (loop ends and binary ends with no errors). I 'm doing something wrong? or its a g++ bug?

If i change the delete[] line to delete[] static_cast<B*>(a); it works on g++ too. But, in real cases, I will do not know the real type so I can not cast to anything.

class A {
public:
  virtual ~A() {}
  virtual int x() = 0;
};

class B : public A {
public:
  B() : _x(1) {}
  virtual ~B() {}
  virtual int x() { return _x; }
private:
  int _x;
};

int main(int argc, char * argv[]) {
  A * a;
  for (unsigned int i = 1; i <= 10; ++i) {
    a = new B[i];
    delete[] a;
  }
return 0;
}
4
  • You can only delete[] what you new-ed. You newed an array of Bs. That's the only thing you can delete[], then. Commented Oct 5, 2018 at 21:11
  • 1
    And this is why std::vector and std::unique_ptr should be the first go toes when needing dynamic allocations. Commented Oct 5, 2018 at 21:13
  • If a major compiler such as g++ had an issue with the toy code you posted, thousands of programmers would have reported the issue. Commented Oct 5, 2018 at 21:17
  • 1
    See stackoverflow.com/questions/6171814/… for an explanation of why you can not delete an array using a pointer to the elements base type Commented Oct 5, 2018 at 21:30

2 Answers 2

4

I 'm doing something wrong? or its a g++ bug?

The behavior of your program is undefined:

If the static type of the object that is being deleted differs from its dynamic type (such as when deleting a polymorphic object through a pointer to base), and if the destructor in the static type is virtual, the single object form of delete begins lookup of the deallocation function's name starting from the point of definition of the final overrider of its virtual destructor. Regardless of which deallocation function would be executed at run time, the statically visible version of operator delete must be accessible in order to compile. In other cases, when deleting an array through a pointer to base, or when deleting through pointer to base with non-virtual destructor, the behavior is undefined.

Sign up to request clarification or add additional context in comments.

5 Comments

The "In other cases" there looks important. It seems to imply that there are some cases in which the bolded statement isn't true. (Or is "In other cases" one of three possibilities, rather than a qualifier for two?)
@JosephSible I think it should be read as: "In other cases: <other cases here>". So the bolded statement is one of those cases.
Ah, that is correct. The actual standard explains that more clearly than cppreference.com does. I'll post a quote from that too.
So, in a real-world example, the user would either allocate an array of the correct type of pointer, or build a container-of-base-pointers one element at a time, and delete it likewise one at a time. Does that sound right?
@TimRandall In a real world example I would start with either a container or a smart pointer in order not to debug memory leaks in the applications a few months later :)
1

From the C++ standard:

In a single-object delete expression, if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined. In an array delete expression, if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.

(emphasis added) That's exactly what you're doing when you delete[] a;, and a segmentation fault is definitely a possible result of undefined behavior.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.