48

what is the difference between deleting a pointer, setting it to null, and freeing it.

delete ptr;

vs.

ptr=NULL;

vs.

free(ptr);
Steve Rowe
  • 19,411
  • 9
  • 51
  • 82
hero
  • 491
  • 1
  • 4
  • 5
  • 2
    C has no concept of `delete`. Do you mean C++ only? – GManNickG May 26 '10 at 06:41
  • 3
    Your question suggests that you come from a language with *garbage collection* like Java or C#. C++ doesn't have this. See my answer for more details. – j_random_hacker May 26 '10 at 06:57
  • @GMan, C has free though which is essentially the same thing in this context. – Steve Rowe May 26 '10 at 07:06
  • 1
    @Steve: Eh, `free` just returns memory allocated with `malloc`. `delete` calls destructors, `operator delete`, etc. – GManNickG May 26 '10 at 07:13
  • Agree with Potatoswatter. At the very least, I think this question would make much more sense if there was another "vs." between `delete ptr;` and `ptr=NULL;`. – j_random_hacker May 27 '10 at 02:14
  • @GMan, you are correct, but I don't think in a relevant way. This is about the difference between setting a pointer to NULL and calling delete. The big difference is leaking memory. The same is true of free vs setting a pointer to NULL. – Steve Rowe May 27 '10 at 07:04

6 Answers6

65

Your question suggests that you come from a language that has garbage collection. C++ does not have garbage collection.

If you set a pointer to NULL, this does not cause the memory to return to the pool of available memory. If no other pointers point to this block of memory, you now simply have an "orphaned" block of memory that remains allocated but is now unreachable -- a leak. Leaks only cause a program to crash if they build up to a point where no memory is left to allocate.

There's also the converse situation, where you delete a block of memory using a pointer, and later try to access that memory as though it was still allocated. This is possible because calling delete on a pointer does not set the pointer to NULL -- it still points to the address of memory that previously was allocated. A pointer to memory that is no longer allocated is called a dangling pointer and accessing it will usually cause strange program behaviour and crashes, since its contents are probably not what you expect -- that piece of memory may have since been reallocated for some other purpose.

[EDIT] As stinky472 mentions, another difference between delete and free() is that only the former calls the object's destructor. (Remember that you must call delete on an object allocated with new, and free() for memory allocated with malloc() -- they can't be mixed.) In C++, it's always best to use static allocation if possible, but if not, then prefer new to malloc().

j_random_hacker
  • 50,331
  • 10
  • 105
  • 169
  • 2
    FTR, this answer was in response to rev 1 of the question: "What's the difference between deleting a pointer and setting it to NULL?" – j_random_hacker May 27 '10 at 02:12
  • 1
    +1 It's also worth pointing out in this new revision that free does not invoke destructors for UDTs and should generally be avoided in C++ (unless one is implementing a memory allocator). – stinky472 Jun 27 '10 at 07:09
  • Also, using malloc/free/realloc/calloc and the like on non-POD types in C++ yields undefined behaviour. – Sebastian Mach Aug 08 '12 at 13:30
  • @phresnel: I think the only problematic one there is `realloc()`, which is allowed to move items in memory. With the others, you can use placement `new` and explicit destructor calls to manage object lifetimes without UB, although of course this is a bit inconvenient and error-prone. – j_random_hacker Aug 08 '12 at 14:25
  • I came up with a question today. When a function ends, it actually frees the pointers(released them), but not deletes them, right? Since deleting a pointer would mean delete its referenced object as well. When writing a function that performs adding nodes to a linked list, we will most likely have a temp pointer in there(call it *tmp), but when the function ends, we cannot dereference that node by accessing *tmp, but the node that was previously referenced by *tmp is still there, already been added to the list, right? The *tmp pointer is freed after the function, but not deleted, right? – Hang Dec 08 '17 at 09:09
  • @Hang: You should really ask this as a separate question. Also it's not clear what you mean by "freeing a pointer" -- usually people would only use "free" or "release" to talk about the pointed-to memory, and this does not happen here: the local pointer variable (usually 4 or 8 bytes) no longer exists after the function returns, but no pointed-to memory is never "freed" or "released" automatically. – j_random_hacker Dec 08 '17 at 10:32
  • @j_random_hacker Thank you very much for your answer! I thought my question is related to this post so I asked here. I think what you said has already answered my question. Basically, the local pointers of a function will no longer exist after the function call, but, the objects that those pointers pointed to are still in the memory. We just cannot access them by those local pointers anymore(since they do not exist anymore), but we may access them by, say if they are nodes in a linked list, by traversing the list using the next pointer of the nodes until we find them. Am I right? – Hang Dec 08 '17 at 10:39
  • @Hang: That's exactly right. (I agree that your question is somewhat related, but it's still a better fit for this site to ask it as a separate question.) – j_random_hacker Dec 08 '17 at 12:10
  • @j_random_hacker I agree with you. I will definitely do this next time. Thank you very much for your help! :D – Hang Dec 08 '17 at 12:28
31

delete will give allocated memory back to the C++ runtime library. You always need a matching new, which allocated the memory on the heap before. NULL is something completely different. A "placeholder" to signify that it points to no address. In C++, NULLis a MACRO defined as 0. So if don't like MACROS, using 0 directly is also possible. In C++0x nullptr is introduced and preferable.

Example:

int* a;        //declare pointer
a = NULL;      //point 'a' to NULL to show that pointer is not yet initialized 
a = new int;   //reserve memory on the heap for int

//... do more stuff with 'a' and the memory it points to

delete a;      //release memory
a = NULL;      //(depending on your program), you now want to set the pointer back to
               // 'NULL' to show, that a is not pointing to anything anymore
Lucas
  • 13,679
  • 13
  • 62
  • 94
  • 3
    technically, you give it back to the C Runtime library which then may or may not give it back to the OS. – shoosh May 26 '10 at 06:38
  • 6
    Actually you give it back to the C++ Runtime library, which may or may not give it back to the C runtime library or OS. – MSalters May 26 '10 at 06:59
5

well, if you created object dynamically(with 'new'), setting pointer to any value does not delete object from memory - and you get a memory leak.

foret
  • 728
  • 6
  • 14
5

As with any indirection, there are two objects involved when using pointers: the referrer (the pointer, in your example ptr) and the referenced object (what it points to, *ptr). You need to learn to differentiate between them.

When you assign NULL to a pointer, only the pointer is affected, the object it refers to is left alone. If the pointer was the last one pointing to that object, you have lost the last referring pointer pointing to it and thus cannot use it anymore. In C++, however, that does not mean the object will be deleted. C++ does not have a garbage collection. So the object is leaked.

In order for objects to be deleted, you will have to delete them manually by passing their address (stored in a pointer) to the delete operator. If you do this, only the object referred to will be affected, the pointer is left alone. It might still point to the address where the object resided in memory, even though that isn't usable anymore. That is called a dangling pointer.

sbi
  • 219,715
  • 46
  • 258
  • 445
  • The pointer is not necessarily an object, for example in `delete new int` or `delete function()` or `delete ptr - 1`. – fredoverflow May 26 '10 at 08:16
  • 1
    @hero: You `delete` objects you obtained using `new`, you `delete[]` arrays obtained using `new[]`, you `free()` memory obtained using `malloc()`, etc. However, in C++, you shouldn't use `malloc()`. What it does is to allocate dynamic __memory__, whereas `new` creates dynamically allocated __objects__. In principle, what `new` does is to [allocate memory __and to create the object__ by calling the type's constructor](http://stackoverflow.com/questions/1820069/1820092#1820092). – sbi May 26 '10 at 10:24
  • @FredOverflow: In C++, an `int` is called an "object", too. I think what you mean is that it doesn't necessarily have to be an lvalue, it could be an rvalue as well. – sbi May 26 '10 at 10:26
  • @FredOverflow: In C++, `42` is a literal (an rvalue) of type `int` and as such it is called "object". An important distinction is made between _lvalues_ and _rvalues_, but, usually, both are called "objects". In C++, "value" and "object" are pretty much synonym, and applied to both built-ins and user-defined types. (In fact, the reason operator overloading was invented was to blur the difference and allow UDTs to be used the same way built-ins are.) – sbi May 26 '10 at 12:04
  • 42 is not an object. Only those rvalues that are of array or class type are objects. All other rvalues aren't objects. (Actually C++03 did miss to say that array rvalues are objects. But that was a defect, and is fixed in the C++0x FCD). – Johannes Schaub - litb May 27 '10 at 19:04
  • @sbi I wasn't talking about the literal `42`, which is an expression, but about the value 42, which is the result of evaluating the expression `42` ;) lvalues and rvalues are kinds of *expressions*, not kinds of objects. An lvalue of type int is an expression that yields an int object, whereas an rvalue of type int is an expression that yields an int value. (For class types, lvalues and rvalues both yield objects.) If you search the standard for "object representation" and "value representation", you will find that objects and values are not the same thing at all. – fredoverflow May 27 '10 at 19:07
  • In fact this is why in my other answer i said "std::string() // create one string object" and not "int() // create one int object" because the latter does not create any object :) – Johannes Schaub - litb May 27 '10 at 19:17
  • @FredOverflow, I've lately been a bit less sure about whether objects are lvalues/rvalues or whether only expressions can be such things. [Temporary objects seem to have such a property](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#177), even if there is no expression referring to them. I believe though that this is just unfortunate wording. What do you think? Is a FCD comment in order? – Johannes Schaub - litb May 27 '10 at 19:20
  • @Johannes Current standard §3.10 1 clearly states "Every expression is either an lvalue or an rvalue", and the current draft clearly separates expressions into lvalues, xvalues, prvalues, glvalues and rvalues (see diagram on page 76). – fredoverflow May 27 '10 at 19:28
  • @FredOverflow i agree so do you think it's a defect introduced by that DR resolution? – Johannes Schaub - litb May 27 '10 at 19:30
  • @Johannes I think we're getting a little off-topic here ;) Maybe you can ask a separate SO question on this topic, I will be happy to participate once I have polished my standardese a little :) – fredoverflow May 27 '10 at 19:44
3

When you create an object using new, you need to use delete to release its memory back to the system. The memory will then be available for others to reuse.


int* a = new int;
delete a;

NULL is just a pre-defined macro that can be assigned a pointer to mean that it does not point to anything.


int* a = new int;
a = NULL;

In the above case, after allocating storage for a, you are assigning NULL to it. However, the memory previously allocated for a was not released and cannot be reused by the system. This is what we call memory leak.

jasonline
  • 8,646
  • 19
  • 59
  • 80
1
int * ptr = null;

Calling free(ptr) will do nothing. According to standard if given pointer is null then no action happens.

Using delete p will also do nothing. C++ standard says that no action will happen because it points to nothing and no type is available.

sloth
  • 99,095
  • 21
  • 171
  • 219