Pointers, deletion and nullptr

If an allocation happens with the new operator we have to deallocate the allocated memory which happens with delete. What it means may not be clear completely. As far as I'm concerned deallocation means freeing that allocated memory for new allocations. Fine up to here. But the pointer (named now dangling) still keeps the that address. Right?
Last edited on
> But the pointer (named now dangling) still keeps the that address. Right?

Right.

For high level code, strongly favour using a smart pointer.

Avoid calling new and delete explicitly.
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rr-newdelete
If you use new outside of a class constructor and delete outside of the destructor, then IMO you definitely should be using smart/managed pointers. If you do use delete outside of a destructor then I'd set the pointer to nullptr after the delete. That way if the pointer is being used when it shouldn't you'll get an exception.

Note that even if you do use a managed pointer then you can still pass a simple memory pointer to functions that need it that don't take/assume memory ownership.
> If you use new outside of a class constructor and delete outside of the destructor ...

Using new outside a constructor or delete outside a destructor is fine in the implementation of low-level code devoted to resource management (for example, in the overloaded assignment operator for a doubly linked list).
Salut tout le monde,
If an allocation happens with the new operator we have to deallocate the allocated memory which happens with delete.


First of all you should not use these two operators which are a source of problems in C++ and even the standard library strongly advises against it unless you have a sharp knowledge of the subject.

Since C++11 you shouldn't need these two operators (new and delete), because you can use smart pointers.

Here are the causes:
* it is much more difficult to manage the FREE STORE or the HEAP by yourself, it is better to leave this task to the standard library instead.
*It is difficult to know if we are releasing memory at the right time.
*We forget to free the memory - in which case we have a memory loss.
*We free the memory while pointers are still referring to that memory - in which case we have a pointer that refers to a memory that is no longer valid.

As far as I'm concerned deallocation means freeing that allocated memory for new allocations. Fine up to here.


Not really, in truth deallocation in C++ means:

1) Destruction of the dynamically allocated object.
2) Finally freeing the space that the dynamically allocated object occupied in memory .

But the pointer (named now dangling) still keeps the that address. Right?


In fact when we apply the delete operator on a pointer that was previously returned by the new operator, the compiler does the deallocation (destroying the dynamically allocated object and freeing its space in the free store), the compiler will make our pointer into a float pointer, that is to say, a float pointer is a pointer that was pointing to a memory space that used to contain an object but no longer does. So you understand that even if you use the delete operator on the pointer, it still contains the address in memory that has been destroyed, so if you dare to use a pointer on which the delete operator has already been applied, the compiler may throw an exception or there will simply be an undefined behavior. Do you understand so far?

Well, let's continue, since I answered your question, so how to solve this problem of float pointer?

You just have to make your pointer null, that is to say give a null value to your pointer.

Before C++11:
type *ptr = NULL;

Since C++11:
type *ptr = nullptr; //(this is recommended by the standard library).

Note: I know I was a bit long but it was worth it for a good understanding and importance of using smart pointers instead of embedded pointers
If you use new outside of a class constructor and delete outside of the destructor, then IMO you definitely should be using smart/managed pointers. If you do use delete outside of a destructor then I'd set the pointer to nullptr after the delete. That way if the pointer is being used when it shouldn't you'll get an exception.


Then it's wrong,

Let's take an example, let's imagine that in a class at the level of its constructor we have the use of the operator new and at the level of its destructor we have a delete, now after instantiation of an object having for type our class and during the execution of our program an exception is raised because of a false manipulation, So the destructor of our class will never be applauded by the compiler since there is an exception the program stops automatically without freeing the space allocated dynamically in the constructor.

Do you see that your argument doesn't really make sense?
Last edited on
ElJos wrote:
Then it's wrong,

Let's take an example, let's imagine that in a class at the level of its constructor we have the use of the operator new and at the level of its destructor we have a delete, now after instantiation of an object having for type our class and during the execution of our program an exception is raised because of a false manipulation, So the destructor of our class will never be applauded by the compiler since there is an exception the program stops automatically without freeing the space allocated dynamically in the constructor.


Consider these two links:

https://stackoverflow.com/questions/2331316/what-is-stack-unwinding
https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization

RAII classes can have a new in the constructor and a delete in the destructor. Even though the resource may be allocated with new, the object itself is on the stack. When an exception is thrown and stack unwinding occurs, all the destructors are called, and hence all the deletes.

By the way a "float pointer" is referred to as a dangling pointer by most people, maybe to avoid confusion with the type float.

I agree with the things you said in your other post.
Thank you all for your answers.
If we delete a pointer (whether it's pointing to an allocated object in memory using new or a copy of another pointer):
1
2
3
4
double* p1 = new double(4.5);
double* p2 = p1;
delete p1;
delete p2;

the compiler destroys that allocated object (that is, it sets that object to zero) up to here we're done with that object and its space (since it also is freed for further usages).
For the dangling pointer we had better set it to nullptr:
1
2
p1 = nullptr;
p2 = nullptr;

this also destroys the pointer as thought there'd not been such a pointer already. So the space already set for the pointer will also be freed for further usages.
All correct, please?
Last edited on
 
delete p2;


No! p2 points to the same memory as p1 (from L2). The memory pointed to by p1 (allocated in L1) is deleted in L3. In this case in L4 p2 is now a dangling pointer. L4 now tries to delete memory already deleted in L3. Don't.

L2 doesn't do an allocation and copy of memory. It just copies the pointers (known as a shallow copy).

In this case you Don't delete p2.

This is the sort of mess you get with raw pointers unless you are very careful. This is why we are saying use managed pointers and not raw pointers.

Don't delete a pointer that is a copy of another pointer.

After L3 you can set both p1 nad p2 to nullptr:

1
2
3
4
double* p1 = new double(4.5);
double* p2 = p1;
delete p1;
p1 = p2 = nullptr;


Last edited on
Yeah, that's right, thanks, that was probably a typo, since this as a mistake is very obvious. @El Jos, thanks you for your answer, and TheIdeasMan thank for pointing out the possible confusion regarding "float" and "dangling". I'm dealing with raw pointers just to get them properly not necessarily for usage, since using modern cpp we rarely need to declare a pointer whether it's raw or smart.

Anyhow, merely to sum up:

1
2
3
4
5
double* p1 = new double(4.5);
double* p2 = p1;
delete p1; // or delete p2;
p1 = nullptr;
p2 = nullptr;

This should totally free allocated objects for the pointers and of the pointers too.
Last edited on
Topic archived. No new replies allowed.