what is the difference between deleting a pointer, setting it to null, and freeing it.
delete ptr;
vs.
ptr=NULL;
vs.
free(ptr);
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().
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
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.
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.
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.
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.
Related
When we declare something dynamically like this
int *ptr = new int [100];
and then change the pointer address (i.e point it to something else)
int pointer[5] = {1,2,1,3,1,};
ptr = pointer ;
now what happens to that memory which contained 100 integers?
is there anyway to regain control of that memory ? and if not, does it lead to a memory leak?
now what happens to that memory which contained 100 integers?
It is "leaked" because you lost the only handle you had to it.
is there anyway to regain control of that memory ?
No, unless you take care to create another handle before re-assigning ptr.
int* ptr = new int[100];
int* ptr2 = ptr;
...
ptr = pointer;
delete [] ptr2;
In real code you would not rely on raw pointers to allocated memory, but rather use whichever RAII type works best for your problem (e.g. std::vector, std::unique_ptr etc.)
In the sample you give, ptr is the only pointer that references the hundred int created by new int [100] (i.e. points at the first element).
Changing the value of ptr does not affect the hundred int. It means that ptr no longer contains the address of the first element.
Practically, after the assignment ptr = pointer, the allocated memory is said to be leaked - it has been allocated, there is no way in standard C++ to access it, and no way in standard C++ to release it (e.g. make the memory it consumes available for reallocation in another new expression).
The only way to keep control of the memory in your case is to store the value of ptr in another variable (or a member of a structure, or an element of an array of pointers, ....) BEFORE reassigning it. If the value of ptr is stored before reassigning ptr, and the place it is stored still exists, the value can be retrieved.
Practically, it would be better to use a standard container (e.g. a std::vector<int>) and not use a new expression in your code. That way, the contents of the container are accessible as long as the container exists (and cease to exist, as far as your program is concerned, when the container does).
Any block of memory allocated with new is unavailable until it is released, either by a corresponding delete or when the process in which the memory was allocated terminates.
The memory allocator actually has no clue about what references you maintain on allocated objects.It just allows you to release the corresponding memory blocks if you manage to provide valid addresses.
How you keep track of these addresses is entirely up to you.
So if for some reason you loose track of a chunk of memory (by overwriting a data pointer as in your example, or simply forgetting to use it at some point to release the memory), you will deprive your system of this bit of memory until the underlying process terminates.
This becomes a memory leak if the "memory lapse" is unintentional, even more so if this occurs repeatedly.
For instance, if you need some data that has the same life span as the process, you can do a one-time allocation and never release the memory (since it will be released automatically upon termination). That could horrify the good practices zealots, but would nevertheless not qualify as a memory leak.
On the other hand, there are other ways of messing up you memory allocator : passing an invalid pointer to delete (including a reference to an already released object, i.e. deleting the same instance of an object more than once, or a pointer to something that was not allocated by new, like a local or global variable) will bring you the wonderful realm of undefined behaviours, which could cause random memory losses, data corruption or nuclear meltdowns.
From my understanding, when you allocate objects on the heap you use
Object* dynamicobject = new Object();
When I call delete I go
delete dynamicobject
I'm confused because I delete the pointer to the instance of that object, but along my line of thinking, you need to actually delete the object in memory itself which requires you to dereference the pointer like
delete *dynamicobject
but this is incorrect.
If you want to change the object a pointer points to, it needs to be dereferenced, and I assumed that the same applied for deletion, but it seems only the pointer can be deleted.
If you do
delete *dynamicobject;
the value given to the delete operator is the value in the dynamic memory location, not the location itself. The delete operator needs to know where the dynamic memory is, so it can reclaim it.
For example, suppose you do:
int *dynamic_int = new int;
*dynamic_int = 10;
If you then did:
delete *dynamic_int;
the delete operator would receive the integer value 10. That doesn't provide the information it needs to reclaim the dynamic memory where that value is stored. But if you do
delete dynamic_int;
the delete operator receives the address of that dynamic memory, and it can reclaim it.
The operators are parallel. new returns a pointer to newly-allocated memory. delete takes a pointer to allocated memory and deletes it. In other words, delete (new ...()) works.
Maybe it would help to consider that delete fundamentally has to work with memory somehow, and not with an object, per se. Thus it needs not only the object but also the object's memory location.
I think you are thinking about destructing the object. When you call new, memory is allocated for the object and its address is returned as a pointer. That pointer is a unique identifier recording exactly which area of memory needs to be deallocated when the object is deleted.
So delete needs to be given the pointer to the memory to deallocate.
But that doesn't kill the object. Killing the object happens by running the destructor and this is where the pointer is dereferenced.
The destructor function is, of course ~Object() {}.
So delete will dereference the pointer to access the actual memory of the object by running the destructor function. After the destructor has run on the dereferenced object the memory address that the object occupied is released back to the runtime system.
So delete needs the pointer which gets dereferenced to destruct the object itself and is then used to determine exactly what memory to release.
delete dynamicobject; does not delete the pointer dynamicobject. Rather, it deletes the object that dynamicobject points to.
You don't have to (and can't) write delete *dynamicobject;, presumably for similar reasons to why you don't have to write dynamicobject = &new Object;.
You only deal in pointers, since dynamic memory allocation is just a big linked list of blocks. When you request a block of size n, the allocator searches the linked list for a block that satisfies the request. When the allocator finds the block, it returns a pointer to said block--that is, the address of the first byte in the block.
Freeing memory simply returns the block into the linked list, so that when you try to allocate memory again, that block may be reused.
All the allocator needs to know is the address of the first byte and the size. That's why it deals only in pointers.
This question already has answers here:
delete vs NULL vs free in c++
(6 answers)
Closed 7 years ago.
Is saying delete pointer and pointer = nullptr the same? Probably not, but does the latter free up memory? What about delete pointer; pointer = nullptr / pointer = nullptr; delete pointer? Why not use that to make a safe way to delete pointers prematurely if required, where they would normally be deleted some other time and cause an error with a normal delete?
pointer = nullptr; is like removing the ink from a business card. You no longer know where the house is located, at least not from looking at that particular business card. But the house is still there.
delete pointer; is like tearing down the house. The business card still tells you where that house used to be, but if you were to drive there (dereference the pointer), you would see the house was gone. Or worse, maybe they put up a nuclear waste storage facility at that address in the meantime.
It is not the same, because while you may be setting the pointer to null, the contents that the pointer pointed to would still be taking up space.
Doing
delete pointer;
pointer = NULL;
Is fine, but
pointer = NULL;
delete pointer;
Is not, since you already set the pointer to NULL, the delete command will have nothing to delete (or so it thinks). You now have a memory leak because whatever the pointer pointed to beforehand (let's say a linked list) is now floating somewhere in your memory and is untrackable by the program.
Is saying delete pointer and pointer = nullptr the same? Probably not, but does the latter free up memory?
A delete expression calls the destructor and deallocates the memory (i.e., returns it to the free store). Setting the pointer to a null pointer does neither of these, and may leak memory or resources if there are no other pointers to the object.
What about delete pointer; pointer = nullptr / pointer = nullptr; delete pointer?
If you delete a pointer that is already null, there is no effect. So the former destroys the object and deallocates the memory and then sets the pointer to null, whereas the latter still leaks because the delete has no effect.
Some people recommend setting a pointer to null after it is deleted, so that if it's deleted a second time due to a bug, it doesn't crash the program. Personally I don't recommend this; I think deleting a pointer twice is a bug even if it has no effect the second time, and that it's good if the program crashes so you can find and fix that bug.
Why not use that to make a safe way to delete pointers prematurely if required, where they would normally be deleted some other time and cause an error with a normal delete?
Not sure what you mean...
deleting the pointer frees the memory that the pointer points to. Just setting the pointer to nullptr will cause a memeory leak as there is no way to now delete the memory the pointer was pointing to.
You can set a pointer to nullptr after you delete it though as it tells you the pointer points to nothing now and if you call delete on it again by accident it is a non op and your program will continue to run.
delete is called that not only to free allocated memory for the object but also that to call the destructor of the object.
If the destructor will not be called then the object will still keep resources.
Of course fundamental types do not have destructors and calling delete will only free memory occupied by an object of a fundamental type.
But in general objects of user-defined types require to call their destructors when they are deleted.
And the pointer shall points to an object. So there is no sense in this sequence of statements
pointer = nullptr; delete pointer;
because nullptr is not a valid address of an object. It is a NULL pointer literal.
Dynamically allocating memory in C++ of course can be accomplished using new or delete. If a pointer dynamically allocated using new is no longer needed in the course of a C++ program, delete can be used in order to dynamically free up computer memory. I think, if my memory serves me correctly, that Stroustrep in one of his books on C++ mentions that malloc and alloc in C afford the compiler rather than the programmer the option to "free up" or "create" memory in contrast to the object-oriented "new" and "delete". If I don't delete the pointer, then I'll run into a rather insidious memory leak, which isn't good.
However, merely deleting a pointer--as Carrano, Helman, and Veroff (CHV) note on pages 151-153 in the 2nd edition of Walls and Mirrors--does not get rid of the pointer. Rather, delete empties the contents of the pointer yet leaves the pointer somewhere in the memory space of the computer.
In any event, CHV then say that the pointer must be set to NULL after using delete in order get rid of this "deleted" construct.
Is the assignment operator being overloaded in this case to accept NULL as a Boolean value? In other words, is the compiler telling the computer that it is false that the pointer ought to exist in the memory space, meaning that I'm telling the compiler to physically stop a bunch of electrons occupying a two bit space from running through my computer? Am I missing something here?
merely deleting a pointer does not get rid of the pointer
Indeed not; it destroys the object that the pointer points to, and deallocates the object's memory. The pointer isn't affected, and ends up pointing to invalid memory.
In any event, CHV then say that the pointer must be set to NULL after using delete in order get rid of this "deleted" construct
No, the pointer will still exist after that; but setting it to null will make sure it's not pointing to invalid memory, which is arguably safer. Of course, it's a much better idea to manage dynamic objects with smart pointers, so you never end up with an invalid pointer in the first place.
Is the assignment operator being overloaded in this case to accept NULL as a Boolean value?
No, NULL isn't a boolean value, it's a null pointer constant; a special pointer value which doesn't point to anything.
In other words, is the compiler telling the computer that it is false that the pointer ought to exist in the memory space, meaning that I'm telling the compiler to physically stop a bunch of electrons occupying a two bit space from running through my computer?
Er, what? No, it's just telling the pointer not to point to anything. It certainly doesn't stop any electrons from occupying any spaces.
Am I missing something here?
I think the main idea you're missing is that the pointer and the thing it points to are separate objects, with separate lifetimes. delete will destroy an object with a dynamic lifetime, but not the pointer that's used to refer to it.
A bit of history might help. First, there was C, with malloc, etc. e.g.:
char *ptr = malloc(100);
strcpy(ptr, "hello, world!");
free(ptr);
printf("%s\n", ptr); /* BAD - but will PROBABLY print "hello, world!" */
malloc allocates 100 bytes, the strcpy populated it, and the free() deallocates it. What's involved in "deallocate" simply means that that memory will now be available for reuse by another call to malloc.
free() does NOT reset any pointers, nor clear the memory - hence printf above will probably still print the string as nothing will (probably) have changed. Of course, any programmer writing something like this deserves to be fired.
In order to avoid the bad usage, since free() won't reset the pointers, it's good practice for us to reset them instead as soon as we free some memory :
free(ptr);
ptr = NULL;
printf("%s\n", ptr); /* Now we get a NULL pointer exception - which is what we want */
We WANT the Null-pointer-exception, since after the free() we shouldn't be using the value of ptr.
With C++, all these arguments are the same. delete does a few more things than free - primarily it calls the objects destructors, etc, but the basic's the same. Pointers are not reset, and the memory's still lying around - and you DO want to know if you're accessing memory that's not allocated to you - and the best way of doing that is setting your pointers to null when you delete the object.
Nulling pointer with nullptr or NULL is used to prevent crashes on double deletes, not to free the memory the pointer actually takes (pointer, not memory it is pointing at). The only time when the actual pointer stops existing is the end of a scope.
The lifetime of the pointer itself, like all other variables, is governed by scope.
void someFunc()
{
int* ptr;
}//ptr dies after this bracket
So always please remember to free the memory a pointer points to before it goes out of scope or you`ll never be able to access it again!
I was working on a piece of code and I was attacked by a doubt: What happens to the memory allocated to a pointer if I assign NULL to that pointer?
For instance:
A = new MyClass();
{...do something in the meantime...}
A = NULL;
The space is still allocated, but there is no reference to it. Will that space be freed later on, will it be reused, will it remain on stack, or what?
This is a classic leak.
As you say, the memory remains allocated but nothing is referencing it, so it can never be reclaimed - until the process exits.
The memory should be deallocated with delete - but using a smart pointer (e.g. std::auto_ptr or boost::shared_ptr (or tr1::shared_ptr) to wrap the pointer is a much safer way of working with pointers.
Here's how you might rewrite your example using std::auto_ptr:
std::auto_ptr a( new MyClass() );
/*...do something in the meantime...*/
a.reset();
(Instead of the call to reset() you could just let the auto_ptr instance go out of scope)
Under most circumstances, that will cause a memory leak in your process. You have several options for managing memory in C++.
Use a delete to manually free memory when you're done with it. This can be hard to get right, especially in the context of exception handling.
Use a smart pointer to manage memory for you (auto_ptr, shared_ptr, unique_ptr, etc.)
C++ does not come with a garbage collector, but nothing prevents you from using one (such as the Boehm GC) if you want to go down that route.
That is a memory leak. You have to delete memory you allocate manually.
A = new MyClass();
{...do something in the meantime...}
A = NULL;
The way I keep track of it is that there are two separate objects. Somewhere on the heap, a MyClass instance is allocated by new. And on the stack, there is a pointer named A.
A is just a pointer, there is nothing magical about out, and it doesn't have some special connection to the heap-allocated MyClass object. It just happens to point to that right now, but that can change.
And on the last line, that is exactly what happens. You change the pointer to point to something else. That doesn't affect other objects. It doesn't affect the object it used to point to, and it doesn't affect the object (if any) that it is set to point to now. Again, A is just a dumb raw pointer like any other. It might be NULL, or it might point to an object on the stack, or it might point to an object on the heap, or it might be uninitialized and point to random garbage. But that's all it does. It points, it doesn't in any way take ownership of, or modify, the object it points to.
You need to delete A;
For regular objects setting the pointer to NULL does nothing but invalidating the pointer, the object is still around in memory, this is particularly true if you notice that you may have more than one pointer to the same object, changing one shouldn't affect the others.
On most modern OSs, the application's memory will be reclaimed at exiting the application. Meanwhile, you have a memory leak.
As per Phil Nash's comment, for every new, there is a corresponding delete, likewise, for every malloc, there is a corresponding free. If the corresponding delete/free is not there, you have a leak.
Hope this helps,
Best regards,
Tom.
C++ does't have garbage collector, like some other languages has (Java, C#, ...) so you must delete allocaled objects yourself.
No, it will be lost to the process forever. You will have a memory leak. If you keep doing this, your program will eventually run out of memory!! To avoid this, delete the object when you no longer need it.
Often people will set the pointer to NULL after deleting it, so that other parts of the program can verify that the object has been deleted, and thereby avoid accessing or deleting it again.
Variables stored on the stack, are the local variables of each function, e.g. int big[10];
Variables stored on the heap, are the variables which you initiated using explicit memory allocation routines such as malloc(), calloc(), new(), etc.
Variables stored on the stack have a lifetime that is equal to the lifetime of the current stack frame. In English, when the function returns, you can no longer assume that the variables hold what you expect them to hold. That's why its a classic mistake to return a variable that was declared local in a function.
By assigning NULL to the pointer you will not free allocated memory. You should call deallocation function to free allocated memory. According to C++ Standard 5.3.4/8: "If the allocated type is a non-array type, the allocation function’s name is operator new and the deallocation function’s name is operator delete". I could suggest the following function to safely delete pointers (with assigning NULL to them):
template<typename T>
inline void SafeDelete( T*& p )
{
// Check whether type is complete.
// Deleting incomplete type will lead to undefined behavior
// according to C++ Standard 5.3.5/5.
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete p;
p = NULL;
}