Home > OS >  Segmentation fault in operator delete[]
Segmentation fault in operator delete[]

Time:11-23

I get segmentation fault exception on the next code:

class A {
public:
    A() {}
    virtual ~A(){}
    double m_d;
};
class B : public A {
public:
    B() {}
    virtual ~B(){}
    int x;
};
int main()
{
    A* ptr = new B[5];
    delete[] ptr;
    return 0;
}

If delete d'tors, no exception. Expected to NOT receive an exception.

Compiler: g (Ubuntu 11.2.0-19ubuntu1) 11.2.0

CodePudding user response:

Array delete doesn't respect virtual destructors. Attempting to pass a base class pointer to it causes undefined behavior.

[expr.delete]/2

... In a single-object delete expression, the value of the operand of delete may be a null pointer value, a pointer value that resulted from a previous non-array new-expression, or a pointer to a base class subobject of an object created by such a new-expression. If not, the behavior is undefined. In an array delete expression, the value of the operand of delete may be a null pointer value or a pointer value that resulted from a previous array new-expression. If not, the behavior is undefined.

Note the second list excluding "base class subobject..." part.

[expr.delete]/3

... In an array delete expression, if the dynamic type of the object to be deleted is not similar to its static type, the behavior is undefined.

Where "static type" is the type as determined at compile-time, "dynamic type" is the type of the most-derived object determined at runtime, and "similar" more or less means "the same type", but allows some differences in constness and more.

CodePudding user response:

This is not allowed, as described here: Why is it undefined behavior to delete[] an array of derived objects via a base pointer?

Excerpt: C 03 Standard under 5.3.5 [expr.delete] p3: In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined

I also made, out of curiosity, logging version:

#include <iostream> 

class A {
public:
    A() {}
    virtual ~A(){ std::cout << m_d << " ; ";}
    double m_d {0.5};
};
class B : public A {
public:
    B() {}
    virtual ~B(){ std::cout << x << " : "; }
    int x {2};
};
int main()
{
    A* ptr = new B[5];
    delete[] ptr;
    std::cout << "Hi, nothing crashed here!\n";
    return 0;
}

https://godbolt.org/z/Y7xGdKd3f

Clang: calls base class destructor using incorrect data

2.07634e-317 ; 0.5 ; 9.88131e-324 ; 2.07634e-317 ; 0.5 ; Hi, nothing crashed here!

Gnu: politely crashes

Program returned: 139

M$: works as expected :)

2 : 0.5 ; 2 : 0.5 ; 2 : 0.5 ; 2 : 0.5 ; 2 : 0.5 ; Hi, nothing crashed here

  •  Tags:  
  • c
  • Related