Asked  7 Months ago    Answers:  5   Viewed   42 times

Is it safe to delete a NULL pointer?

And is it a good coding style?

 Answers

57

delete performs the check anyway, so checking it on your side adds overhead and looks uglier. A very good practice is setting the pointer to NULL after delete (helps avoiding double deletion and other similar memory corruption problems).

I'd also love if delete by default was setting the parameter to NULL like in

#define my_delete(x) {delete x; x = NULL;}

(I know about R and L values, but wouldn't it be nice?)

Tuesday, June 1, 2021
 
Maury
answered 7 Months ago
84

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.

Friday, June 4, 2021
 
NewPHP
answered 6 Months ago
58

7.20.3.2 The free function

Synopsis

#include <stdlib.h> 
void free(void *ptr); 

Description

The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs.

See ISO-IEC 9899.

That being said, when looking at different codebases in the wild, you'll notice people sometimes do:

if (ptr)
  free(ptr);

This is because some C runtimes (I for sure remember it was the case on PalmOS) would crash when freeing a NULL pointer.

But nowadays, I believe it's safe to assume free(NULL) is a nop as per instructed by the standard.

Friday, June 4, 2021
 
LukeP
answered 6 Months ago
77

You're misunderstanding what delete does. All delete does is call the destructor, and tell the allocator that that memory is free. It doesn't change the actual pointer. Anything beyond that is undefined.

In this case, it does nothing to the actual data pointed to. That pointer points to the same data it pointed to before, and calling methods on it works just fine. However, this behavior is not guaranteed; in fact, it's explicitly unspecified. delete could zero out the data; or the allocator could allocate that same memory for something else, or the compiler could just refuse to compile this.

C++ allows you to do many unsafe things, in the interest of performance. This is one of them. If you want to avoid this kind of mistake, it's a good idea to do:

delete ptr;
ptr = NULL;

to ensure that you don't try to reuse the pointer, and will crash immediately if you do rather than having undefined behavior.

Saturday, June 26, 2021
 
steros
answered 6 Months ago
77

It's valid.

If class B contains the original member,

B doesn't contain D::Foo, so no.

or is a base [...] of the class containing the original member

B is a base of D, so this holds. As a result:

the resulting pointer to member points to the original member

Clause 5.2.9 9 says you can upcast only if you can also downcast, as specified in § 4.11:

An rvalue of type “pointer to member of B of type cv T,” where B is a class type, can be converted to an rvalue of type “pointer to member of D of type cv T,” where D is a derived class (clause 10) of B. If B is an inaccessible (clause 11), ambiguous (10.2) or virtual (10.1) base class of D, a program that necessitates this conversion is ill-formed.

This just says you can downcast as long as B is accessible, isn't virtual and only appears once in D's inheritance diagram.

The danger inherent in upcasting method pointers is that you could call mp on an object whose actual type is B. As long as a code block that deals with D::* also deals with D*, you can avoid this.

Tuesday, August 3, 2021
 
Tapha
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share