Jack
Jack

Reputation: 110

Operator new/delete & destructors

So I'm a beginner trying to get to grips with operator new. What's wrong with my destructor?

class arr{
public:
    arr(){
        pool=::operator new(100*sizeof(double));
    }
    ~arr(){
        ::operator delete(pool);
    }
    void* pool;
};

int main()
{
    arr a;
    a.~arr(); //If I comment this out it's ok.

    void* pool2=::operator new(100*sizeof(double)); //Works
    ::operator delete(pool2); //Fine.

    system("pause");
    return 0;
}

Leaving a.~arr(); in gives me this error:

Debug assertion failed! File: dbgdel.cpp line: 52

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

I can't see why pool2 works fine but using the class gives me problems. Also the error only pops up after the system "pauses", which is after a.~arr() is called???

Thanks!

Upvotes: 1

Views: 1416

Answers (3)

sbi
sbi

Reputation: 224039

The problem is that you explicitly invoke the destructor on a (a.~arr()), while the destructor will already be invoked automatically when a goes out of scope at the end of main(). When the destructor is called for the second time, it is called on an already destructed object. Technically, this leads to Undefined Behavior (which is a way to say that any result will be fine according to the C++ standard). In practice this code will likely just execute the destructor again, passing the address stored in the memory location that used to be a.pool to the ::operator delete() (which might or might not be what the constructor stored there), which is caught by the Debug runtime.

What you should do instead if you want a to be deleted in the middle of main() is to introduce an additional scope:

int main()
{
  {
    arr a;
  } //a will be deleted here

  // rest of main

}

Another way would be to not to use an automatic object, but a dynamic one, for which you can set a lifetime.


But there's another problem with your code, which you didn't ask about, but which I nevertheless feel a need to point out:

Your class urgently needs a copy constructor and a assignment operator. (At the very least, declare them private in order to disallow copying.) As per the Rule Of Three, the fact that you need a destructor should give you a hint that the other two are needed as well.
You can avoid all the hassle by not attempting to manually manage dynamically allocated memory. Instead use a type which does this for you:

class arr{
public:
    arr() : pool(100*sizeof(double)) {

    }
    // ~arr() // not needed any longer
    std::vector<char> pool;
};

Upvotes: 6

Chenna V
Chenna V

Reputation: 10473

you don't need to call destructor for objects created on stack. The variable 'a' is on stack and will be deleted automatically when out of scope.

Upvotes: 0

James
James

Reputation: 5425

Well, at a glance, you should not be explicitly calling the destructor. Instead use scoping to force a out of scope and call the destructor.

int main()
{
    {
        arr a;
    } //This calls destructor of a

    //Rest of code
}

Otherwise the destructor of a gets called twice: once when you call it and again when a goes out of scope.

EDIT:

Here ya go.

http://www.parashift.com/c++-faq-lite/dtors.html

Upvotes: 7

Related Questions