What Happens in a Double Delete

What happens in a double delete?

It causes undefined behaviour. Anything can happen. In practice, a runtime crash is probably what I'd expect.

Double delete of data doesn't crash

The behavior of "Undefined behavior" is just undefined. That means, no one put effort into that cases because that cases should not happen. Even a working program can be "Undefined behavior".

In your special case of an double delete, what happens, really depends on the implementation of the allocator. A usual implementation is to put released memory into a list and a next allocation will be satisfied with an element out of this list. If you double delete a chunk of memory, it will be added to the list twice. And then two allocation will be satisfied with the very same chunk of memory and thus two object will be created at the same memory location.

BTW: You destructor is already broken, as it doesn't use the array delete.

What exactly happens if you delete an object? (gcc) (When double-delete crashes?)

It is very dependent on the implementation of the memory allocator itself, not to mention any application dependent failures as overwritting v-table of some object. There are numerous memory allocator schemes all of which differ in capabilities and resistance to double free() but all of these share one common property: your application will crash at some time after the second free().

The reason for the crash is usually that memory allocator dedicates small amount of memory before(header) and after(footer) each allocated chunk of memory to store some implementation specific details. Header usually defines size of the chunk and address of the next chunk. Footer is usually pointer to the header of the chunk. Deleting twice usually at least involves checking if adjacent chunks are free. Thus your program will crash if:

1) pointer to the next chunk has been overwritten and the second free() causes segfault when trying to access the next chunk.

2) the footer of the previous chunk has been modified and access to the header of the previous chunk causes segfault.

If the application survives, it means that free() has either corrupted memory in various locations or will add free chunk which overlaps one of already free chunks, leading to data corruption in the future. Eventually your program will segfault at one of following free() or malloc() involving the corrupted memory areas.

How can I avoid double deleting variables in c++?

Generally speaking the best way to avoid double delete is to not allocate memory directly with new. There are various smart pointers you can use like scoped_ptr and shared_ptr, and in your case you can use std::Vector:

typedef std::vector<int> Ints;

void test(const Ints& input, Ints& output)
{
if(input[0] == 0) {
output = input;
}
}

Ints input(3);
Ints output(3);

input[0] = 0;

test(input, output);

Double Delete using Shared Pointers, even though there is still a shared_ptr to the object, its destructor is being called

GameObject::GameObject()
{
shared_ptr<GameObject> ptr(this);
GameEventManager::GetGameEventManager()->RegisterGameObject(ptr);
}

The ptr in this function does not share ownership with any other shared_ptr constructed independently, like the one declared at shared_ptr<Player> sptrPlayer(new Player);. Creating two shared_ptr from raw pointers, rather than copying the first one, generally leads to a double delete.

Instead, you could do something like this:

class GameObject :
public std::enable_shared_from_this<GameObject>
{
protected:
GameObject(); // creates the original shared_ptr
virtual ~GameObject();
};

class Player : public GameObject
{
public:
static std::shared_ptr<Player> create();
private:
Player() : GameObject() {}
virtual ~Player() {}
};

std::shared_ptr<Player> Player::create() {
return dynamic_pointer_cast<Player>((new Player)->shared_from_this());
}

Is it safe to delete a nullptr twice in C++?

Is it safe to delete a nullptr twice in C++?

Yes (in all standard versions of C++). It is guarnteed to work (by work, I mean it doesn't do anyting).

Deletion has no effects if the argument is a null pointer. The compiler that the presenter describes did not conform to the C++ standard. The described compiler also was from the 80's, so it was made before C++ was standardised. The presenter is wrong in saying that you can't delete the null pointer twice if they are referring to standard C++ which does seem to be implied.

It is true that deletion may indirectly cause the program to behave as if the value of the argument pointer was changed (and by as-if rule that means that they effectively can change the value), but only in case where the pointer was non-null and is thus invalidated by the deletion. In fact, this allowance applies to all pointer objects that had the same value as all of them are thereby invalidated. This is because all ways that could observe the value of an invalid pointer are either undefined or implementation defined behaviour.

Move constructor and double delete

That's because you are not actually "stealing", you're just copying, and so you'll delete 2 times the same pointer, as you noticed.

To actually "steal" the data, set the original data to nullptr, as it no longer belongs to that object.

A(A&& t)
: name("move")
{
data = t.data;
t.data = nullptr; //'t' doesn't own its data anymore
cout<<"i am move\n";
}

You could also use std::swap (thanks @RemyLebeau):

A(A&& t) : name("move"), data(nullptr)
{
std::swap(data, t.data);
cout << "i am move\n";
}

Is there any method to safe handle twice freeing memory by delete-expression?

so that the application does not crash

This is just a side-effect, an implementation detail of the real problem. Double deleting causes undefined behavior according to the standard.

There is no way to turn a program exhibiting undefined behavior back into one defined so no, there is no way to handle it safely.


Ideally you shouldn't be using new or delete at all.



Related Topics



Leave a reply



Submit