What happens in a double delete?

2019-01-03 16:53发布

Obj *op = new Obj;
Obj *op2 = op;
delete op;
delete op2; // What happens here?

What's the worst that can happen when you accidentally double delete? Does it matter? Is the compiler going to throw an error?

7条回答
甜甜的少女心
2楼-- · 2019-01-03 17:51

Everyone already told you that you shouldn't do this and that it will cause undefined behavior. That is widely known, so let's elaborate on this on a lower level and let's see what actually happens.

Standard universal answer is that anything can happen, that's not entirely true. For example, the computer will not attempt to kill you for doing this (unless you are programming AI for a robot) :)

The reason why there can't be any universal answer is that as this is undefined, it may differ from compiler to compiler and even across different versions of same compiler.

But this is what "roughly" happens in most cases:

delete consist of 2 primary operations:

  • it calls the destructor if it's defined
  • it somehow frees the memory allocated to the object

So, if your destructor contains any code that access any data of class that already was deleted, it may segfault OR (most likely) you will read some nonsense data. If these deleted data are pointers then it will most likely segfault, because you will attempt to access memory that contains something else, or doesn't belong to you.

If your constructor doesn't touch any data or isn't present (let's not consider virtual destructors here for simplicity), it may not be a reason for crash in most compiler implementations. However, calling a destructor is not the only operation that is going to happen here.

The memory needs to be free'd. How it's done depends on implementation in compiler, but it may as well execute some free like function, giving it the pointer and size of your object. Calling free on memory that was already deleted may crash, because the memory may not belong to you anymore. If it does belong to you, it may not crash immediately, but it may overwrite memory that was already allocated for some different object of your program.

That means one or more of your memory structures just got corrupted and your program will likely crash sooner or later or it might behave incredibly weirdly. The reasons will not be obvious in your debugger and you may spend weeks figuring out what the hell just happened.

So, as others have said, it's generally a bad idea, but I suppose you already know that. Don't worry though, innocent kitten will most likely not die if you delete an object twice.

Here is example code that is wrong but may work just fine as well (it works OK with GCC on linux):

class a {};

int main()
{
    a *test = new a();
    delete test;
    a *test2 = new a();
    delete test;
    return 0;
}

If I don't create intermediate instance of that class between deletes, 2 calls to free on same memory happens as expected:

*** Error in `./a.out': double free or corruption (fasttop): 0x000000000111a010 ***

To answer your questions directly:

What is the worst that can happen:

In theory, your program causes something fatal. It may even randomly attempt to wipe your hard drive in some extreme cases. The chances depends on what your program actually is (kernel driver? user space program?).

In practice, it would most likely just crash with segfault. But something worse might happen.

Is the compiler going to throw an error?

It shouldn't.

查看更多
登录 后发表回答