Is It Safe to Delete a Void Pointer

Is it safe to delete a void pointer?

It depends on "safe." It will usually work because information is stored along with the pointer about the allocation itself, so the deallocator can return it to the right place. In this sense it is "safe" as long as your allocator uses internal boundary tags. (Many do.)

However, as mentioned in other answers, deleting a void pointer will not call destructors, which can be a problem. In that sense, it is not "safe."

There is no good reason to do what you are doing the way you are doing it. If you want to write your own deallocation functions, you can use function templates to generate functions with the correct type. A good reason to do that is to generate pool allocators, which can be extremely efficient for specific types.

As mentioned in other answers, this is undefined behavior in C++. In general it is good to avoid undefined behavior, although the topic itself is complex and filled with conflicting opinions.

How can deleting a void pointer do anything other than invoke the global delete operator?

A void* is a pointer to an object of unknown type. If you do not know the type of something, you cannot possibly know how that something is to be destroyed. So I would argue that, no, there is not "really only one sensible way to deal with such a delete operation". The only sensible way to deal with such a delete operation, is to not deal with it. Because there is simply no way you could possibly deal with it correctly.

Therefore, as the original answer you linked to said: deleting a void* is undefined behavior ([expr.delete] §2). The footnote mentioned in that answer remains essentially unchanged to this day. I'm honestly a bit astonished that this is simply specified as undefined behavior rather than making it ill-formed, since I cannot think of any situation in which this could not be detected at compile time.

Note that, starting with C++14, a new expression does not necessarily imply a call to an allocation function. And neither does a delete expression necessarily imply a call to a deallocation function. The compiler may call an allocation function to obtain storage for an object created with a new expression. In some cases, the compiler is allowed to omit such a call and use storage allocated in other ways. This, e.g., enables the compiler to sometimes pack multiple objects created with new into one allocation.

Is it safe to call the global deallocation function on a void* instead of using a delete expression? Only if the storage was allocated with the corresponding global allocation function. In general, you can't know that for sure unless you called the allocation function yourself. If you got your pointer from a new expression, you generally don't know if that pointer would even be a valid argument to a deallocation function, since it may not even point to storage obtained from calling an allocation function. Note that knowing which allocation function must've been used by a new expression is basically equivalent to knowing the dynamic type of whatever your void* points to. And if you knew that, you could also just static_cast<> to the actual type and delete it…

Is it safe to deallocate the storage of an object with trivial destructor without explicitly calling the destructor first? Based on, [basic.life] §1.4, I would say yes. Note that, if that object is an array, you might still have to call the destructors of any array elements first. Unless they are also trivial.

Can you rely on common compiler implementations to produce the behavior you deem reasonable? No. Having a formal definition of what exactly you can rely on is literally the whole point of having a standard in the first place. Assuming you have a standard-conforming implementation, you can rely on the guarantees the standard gives you. You can also rely on any additional guarantees the documentation of a particular compiler may give you, so long as you use that particular version of that particular compiler to compile your code. Beyond that, all bets are off…

How to properly delete an object that is a void pointer?

If you know (for sure) what type it points to, then cast:

delete static_cast<foo*>(obj->foo_obj);

If you've lost track of the type, then you'll need to redesign.

c++ do I need to manually delete a void* pointer which is then pointing to another concrete type?

That all depends on how the int you're pointing to was allocated, you only delete what you new.


Correct (the int is new'd):

int* a = new int;
void* p = a;

//somewhere later...

delete static_cast<int*>(p);

Bad (the int is automatically managed):

int a = 0;
void* p = &a;

//somewhere later...

delete static_cast<int*>(p);

Answering the comment code, doing:

int* a = new int; 
void* p = a;

delete p;

Is never okay. You should never delete through a void*, it's undefined behavior.


side note : in modern C++ you really shouldn't be using new or delete, stick with smart pointers or standard containers.

Deleting void pointer after assigning it with original type

Calling delete on a void pointer is undefined behavior[Ref ]. You should not do it at all. You are not calling delete on a void pointer but on pointer of type Sample which is fine.

[Ref ]
C++ Standard :section 5.3.5/3:

In the first alternative (delete
object), if the static type of the
operand is different from its dynamic
type, the static type shall be a base
class of the operand’s dynamic type
and the static type shall have a
virtual destructor or the behavior is
undefined. 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.

footnote:

This implies that an object cannot be
deleted using a pointer of type void*
because there are no objects of type
void

Deleting a void pointer in C++

If possible, change this code to use a struct containing all the necessary subobjects.

If we just go ahead and check that all the types used are POD and blindly assume there are no alignment issues and that the compiler isn't falling into any strict aliasing traps, then yes, you can change the deletes to

delete[] static_cast<unsigned char*>(a[0]);
delete[] static_cast<unsigned char*>(a[1]);

and have slightly safer behavior.

Does deleting void pointer guarantee to delete right size?

Deleting through a void* results in undefined behavior, so you are guaranteed nothing.

5.3.5 Delete [expr.delete]


1 The delete-expression operator destroys a most derived object (1.8) or array created by a new-expression.

[...]

The operand shall have a pointer to object type, or a class type having a single non-explicit conversion function (12.3.2) to a pointer to object type. The result has type void.78

78) This implies that an object cannot be deleted using a pointer of type void* because void is not an object type.

Emphasis mine.


So even though you said not to say it, the answer is to create some form of smart pointer. It would need to use type-erasure to hide the type externally (allowing the heterogeneous list), but internally keep track of the type it was given and how to delete it. Something much like boost::any.



Related Topics



Leave a reply



Submit