Context: I'm trying to wrap my head around pointers, we just saw them a couple of weeks ago in school and while practicing today I ran into a silly? issue, it can be super straightforward to you but I have little to none programming experience.
I've seen quite a few questions over in SO about deleting pointers but they all seem to be related to deleting a class and not a 'simple' pointer (or whatever the proper term might be), here's the code I'm trying to run:
#include <iostream>;
using namespace std;
int main() {
int myVar,
*myPointer;
myVar = 8;
myPointer = &myVar;
cout << "delete-ing pointers " << endl;
cout << "Memory address: " << myPointer << endl;
// Seems I can't *just* delete it, as it triggers an error
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// Error: a.out(14399) malloc: *** error for object 0x7fff61e537f4:
// pointer being freed was not allocated
// *** set a breakpoint in malloc_error_break to debug
// Abort trap: 6
// Using the new keyword befor deleting it works, but
// does it really frees up the space?
myPointer = new int;
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// myPointer continues to store a memory address.
// Using NULL before deleting it, seems to work.
myPointer = NULL;
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// myPointer returns 0.
}
So my questions are:
Why won't the first case work? Seems the most straightforward use to use and delete a pointer? The error says the memory wasn't allocated but 'cout' returned an address.
On the second example the error is not being triggered but doing a cout of the value of myPointer still returns a memory address?
Does #3 really work? Seems to work to me, the pointer is no longer storing an address, is this the proper way to delete a pointer?
Sorry for the long question, wanted to make this as clear as possible, also to reiterate, I have little programming experience, so if someone could answer this using layman's terms, it would be greatly appreciated!
1 & 2
myVar = 8; //not dynamically allocated. Can't call delete on it.
myPointer = new int; //dynamically allocated, can call delete on it.
The first variable was allocated on the stack. You can call delete only on memory you allocated dynamically (on the heap) using the new operator.
3.
myPointer = NULL;
delete myPointer;
The above did nothing at all. You didn't free anything, as the pointer pointed at NULL.
The following shouldn't be done:
myPointer = new int;
myPointer = NULL; //leaked memory, no pointer to above int
delete myPointer; //no point at all
You pointed it at NULL, leaving behind leaked memory (the new int you allocated).
You should free the memory you were pointing at. There is no way to access that allocated new int anymore, hence memory leak.
The correct way:
myPointer = new int;
delete myPointer; //freed memory
myPointer = NULL; //pointed dangling ptr to NULL
The better way:
If you're using C++, do not use raw pointers. Use smart pointers instead which can handle these things for you with little overhead. C++11 comes with several.
I believe you're not fully understanding how pointers work.
When you have a pointer pointing to some memory there are three different things you must understand:
- there is "what is pointed" by the pointer (the memory)
- this memory address
- not all pointers need to have their memory deleted: you only need to delete memory that was dynamically allocated (used new operator).
Imagine:
int *ptr = new int;
// ptr has the address of the memory.
// at this point, the actual memory doesn't have anything.
*ptr = 8;
// you're assigning the integer 8 into that memory.
delete ptr;
// you are only deleting the memory.
// at this point the pointer still has the same memory address (as you could
// notice from your 2nd test) but what inside that memory is gone!
When you did
ptr = NULL;
// you didn't delete the memory
// you're only saying that this pointer is now pointing to "nowhere".
// the memory that was pointed by this pointer is now lost.
C++ allows that you try to delete a pointer that points to null but it doesn't actually do anything, just doesn't give any error.
Pointers are similar to normal variables in that you don't need to delete them. They are removed from memory at the end of a functions execution and/or the end of the program.
You can however use pointers to allocate a 'block' of memory, for example like this:
int *some_integers = new int[20000]
This will allocate memory space for 20000 integers. Useful, because the Stack has a limited size and you might want to mess about with a big load of 'ints' without a stack overflow error.
Whenever you call new, you should then 'delete' at the end of your program, because otherwise you will get a memory leak, and some allocated memory space will never be returned for other programs to use. To do this:
delete [] some_integers;
Hope that helps.
There is a rule in C++, for every new there is a delete.
Why won't the first case work? Seems the most straightforward use to use and delete a pointer? The error says the memory wasn't allocated but 'cout' returned an address.
new is never called. So the address that cout prints is the address of the memory location of myVar, or the value assigned to myPointer in this case. By writing:
myPointer = &myVar;
you say:
myPointer = The address of where the data in myVar is stored
On the second example the error is not being triggered but doing a cout of the value of myPointer still returns a memory address?
It returns an address that points to a memory location that has been deleted. Because first you create the pointer and assign its value to myPointer, second you delete it, third you print it. So unless you assign another value to myPointer, the deleted address will remain.
Does #3 really work? Seems to work to me, the pointer is no longer storing an address, is this the proper way to delete a pointer?
NULL equals 0, you delete 0, so you delete nothing. And it's logic that it prints 0 because you did:
myPointer = NULL;
which equals:
myPointer = 0;
You are trying to delete a variable allocated on the stack. You can not do this
Deleting a pointer does not destruct a pointer actually, just the memory occupied is given back to the OS. You can access it untill the memory is used for another variable, or otherwise manipulated. So it is good practice to set a pointer to NULL (0) after deleting.
Deleting a NULL pointer does not delete anything.
int value, *ptr;
value = 8;
ptr = &value;
// ptr points to value, which lives on a stack frame.
// you are not responsible for managing its lifetime.
ptr = new int;
delete ptr;
// yes this is the normal way to manage the lifetime of
// dynamically allocated memory, you new'ed it, you delete it.
ptr = nullptr;
delete ptr;
// this is illogical, essentially you are saying delete nothing.
Related
This Question statement is came in picture due to statement made by user (Georg Schölly 116K Reputation) in his Question Should one really set pointers to `NULL` after freeing them?
if this Question statement is true
Then How data will corrupt I am not getting ?
Code
#include<iostream>
int main()
{
int count_1=1, count_2=11, i;
int *p=(int*)malloc(4*sizeof(int));
std::cout<<p<<"\n";
for(i=0;i<=3;i++)
{
*(p+i)=count_1++;
}
for(i=0;i<=3;i++)
{
std::cout<<*(p+i)<<" ";
}
std::cout<<"\n";
free(p);
p=(int*)malloc(6*sizeof(int));
std::cout<<p<<"\n";
for(i=0;i<=5;i++)
{
*(p+i)=count_2++;
}
for(i=0;i<=3;i++)
{
std::cout<<*(p+i)<<" ";
}
}
Output
0xb91a50
1 2 3 4
0xb91a50
11 12 13 14
Again it is allocating same memory location after freeing (0xb91a50), but it is working fine, isn't it ?
You do not reuse the old pointer in your code. After p=(int*)malloc(6*sizeof(int));, p point to a nice new allocated array and you can use it without any problem. The data corruption problem quoted by Georg would occur in code similar to that:
int *p=(int*)malloc(4*sizeof(int));
...
free(p);
// use a different pointer but will get same address because of previous free
int *pp=(int*)malloc(6*sizeof(int));
std::cout<<p<<"\n";
for(i=0;i<=5;i++)
{
*(pp+i)=count_2++;
}
p[2] = 23; //erroneouly using the old pointer will corrupt the new array
for(i=0;i<=3;i++)
{
std::cout<<*(pp+i)<<" ";
}
Setting the pointer to NULL after you free a block of memory is a precaution with the following advantages:
it is a simple way to indicate that the block has been freed, or has not been allocated.
the pointer can be tested, thus preventing access attempts or erroneous calls to free the same block again. Note that free(p) with p a null pointer is OK, as well as delete p;.
it may help detect bugs: if the program tries to access the freed object, a crash is certain on most targets if the pointer has been set to NULL whereas if the pointer has not been cleared, modifying the freed object may succeed and result in corrupting the heap or another object that would happen to have been allocated at the same address.
Yet this is not a perfect solution:
the pointer may have been copied and these copies still point to the freed object.
In your example, you reuse the pointer immediately so setting it to NULL after the first call to free is not very useful. As a matter of fact, if you wrote p = NULL; the compiler would probably optimize this assignment out and not generate code for it.
Note also that using malloc() and free() in C++ code is frowned upon. You should use new and delete or vector templates.
int main() {
int* i = new int(1);
i++;
*i=1;
delete i;
}
Here is my logic:
I increment I by 1, and then assign a value to it. Then I delete the I, so I free the memory location while leaking the original memory. Where is my problem?
I also tried different versions. Every time, as long as I do the arithmetics and delete the pointer, my program crashes.
What your program shows is several cases of undefined behaviour:
You write to memory that hasn't been allocated (*i = 1)
You free something that you didn't allocate, effectively delete i + 1.
You MUST call delete on exactly the same pointer-value that you got back from new - nothing else. Assuming the rest of your code was valid, it would be fine to do int *j = i; after int *i = new int(1);, and then delete j;. [For example int *i = new int[2]; would then make your i++; *i=1; valid code]
Who allocates is who deallocates. So you should not be able to delete something you did not new by yourself. Furthermore, i++;*i=1; is UB since you may access a restricted memory area or read-only memory...
The code made no sense . I think You have XY problem. If you could post your original problem there will be more chance to help you.
In this case you need to have a short understanding how the heap memory management works. in particular implementation of it, when you allocate an object you receive a pointer to the start of the memory available to you to work with. However, the 'really' allocated memory starts a bit 'earlier'. This means the allocated block is a bit more than you have requested to allocate. The start of the block is the address you have received minus some offset. Thus, when you pass the incremented pointer to the delete it tries to find the internal information at the left side of it. And because your address is now incremented this search fails what results in a crash. That's in short.
The problem lies here:
i++;
This line doesn't increment the value i points to, but the pointer itself by the number of bytes an int has (4 on 32-bit platform).
You meant to do this:
(*i)++;
Let's take it step by step:
int* i = new int(1); // 1. Allocate a memory.
i++; // 2. Increment a pointer. The pointer now points to
// another location.
*i=1; // 3. Dereference a pointer which points to unknown
// memory. This could cause segmentation fault.
delete i; // 4. Delete the unknown memory which is undefined
// behavior.
In short: If you don't own a piece of memory you can't do arithmetic with it neither delete it!
int main()
{
int *pnPtr = new int;
delete pnPtr;
*pnPtr = 4;
cout<<*pnPtr;
}
Ans) 4 while I tried to execute in visual studio 2010.
Please, explain me how 4 is displayed as output?
what did you expect it to return?
Understand, that delete only frees the allocated memory pointed at, but leaves the pointer as it is. You can still use the pointer to do something to the pointed address.
int main()
{
int *pnPtr = new int; // allocate memory, pnPtr now points to it
delete pnPtr; // delete allocated memory, pnPtr still points to that location
*pnPtr = 4; // set memory at pointed address to 4
cout<<*pnPtr;
}
The pointer pnPtr still points to somewhere in memory, calling delete does not change the value of pnPtr itself. The memory is just no longer allocated for your process.
delete does not change the value of the pointer, it destroys the int size memory association but if not reallocated then it can be available. That has happened in your case.
Issue is due to Dangling pointers that arise during object destruction, when an object that has an incoming reference(pointer) is freed or de-allocated, without modifying the value of the pointer, so that the pointer still points to the memory location of the de-allocated memory.
Assume if the system reallocates the previously freed memory to another process, if the original program then de-references the (now) dangling pointer, unpredictable behavior may result, as the memory may now contain completely different data. This is especially the case if the program writes data to memory pointed by a dangling pointer a silent corruption of unrelated data may result, leading to:
Subtle bugs that can be extremely difficult to find, or
cause segmentation faults or
general protection faults.
So, it is recommended to reset the freed/deleted pointer as follows:
int main()
{
int *pnPtr = new int;
delete pnPtr;
pnPtr = null;
// To-do Logic
return 0;
}
My question:
int* x = new int;
cout << x<<"\n";
int* p;
cout << p <<"\n";
p = x;
delete p;
cout << p <<"\n";
I wrote this purely by myself to understand the pointer and to understand (also get lost in) the dynamic new and delete.
My XCode can compile the program and return the following results:
0x100104250
0x0
0x100104250
I know I can only call delete on dynamically allocated memory.
However, I called delete on p in the above program and it compiles.
Could anyone explain this to me?
Why could I delete p?
Moreover, I found if the program changes to the following:
int* x = new int;
int* p;
cout << p <<"\n";
delete p;
cout << p <<"\n";
Then my Xcode again compiles and returns me:
0x0
0x0
Program ended with exit code: 0
and now, I got completely lost:(.
Could anyone please explain me this ?
Why I could delete p since it has nothing to with x?
Since Xcode compiles successfully, I assume the above two programs are correct for computer.
However, I think it is again the statement of "only call delete on dynamic allocated memory".
Or probably, I didn't fully understand what is pointer and what is dynamic allocated memory.
I found this post when I searched online.
But I don't think it is like my case.
Please help me out.
I would like to ask one more question. The code is here about binary search tree.
From line 28 to 32, it deals with deleting a node with one child.
I put this part of code here, in case the weblink does not work.
else if(root->left == NULL) {
struct Node *temp = root;
root = root->right;
delete temp;
}
It is these codes leading me ask the above the question regarding pointer.
Following the answer given by this post.
Is it correct to understand the code in the following way?
I cannot firstly link the parent node of root to right child of root.
and then delete the root node, as the subtree beneath the root node will also be deleted.
So I must create a temp pointer, pointing to the memory slot, which is pointed to by root.
Then I link the parent node of root to right child of root.
and now, I can safely delete the memory slot pointed by "root", (i.e. temp as they both point to the same memory).
In this way, I release the memory and also keep the link between parent and children.
In addition, the temp is still there and still points to "that" memory slot.
Should I set it to NULL after deletion?
Thank you all again in advance.
Yaofeng
Yes, you can only call delete on memory which was allocated via new. Notice that it's the address of the memory (the value of the pointer) which matters, and not the variable storing the pointer. So, your first code:
int* x = new int; //(A)
cout << x<<"\n";
int* p;
cout << p <<"\n";
p = x; //(B)
delete p; //(C)
cout << p <<"\n"; //(D)
Line (A) allocates memory dynamically at some address (0x100104250 in your example output) and stores this address in variable x. The memory is allocated via new, which means that delete must eventually be called on address 0x100104250.
Line (B) assigns the address 0x100104250 (value of pointer x) into the pointer p. Line (C) then calls delete p, which means "deallocate the memory pointed to by p." This means it calls delete on address 0x100104250, and all is well. The memory at address 0x100104250 was allocated via new, and so is not correctly allocated via delete. The fact that you used a different variable for storing the value plays no role.
Line (D) just prints out the value of the pointer. delete acts on the memory to which a pointer points, not on the pointer itself. The value of the pointer stays the same - it still points to the same memory, that memory is just no longer allocated.
The second example is different - you're calling delete p when p was not initialised to anything. It points to a random piece of memory, so calling delete on it is of course illegal (technically, it has "Undefined Behaviour", and will most likely crash).
It seems that in your particular example, you're running a debug build and your compiler is "helpfully" initialising local variables to 0 if you don't initialise them yourself. So it actually causes your second example to not crash, since calling delete on a null pointer is valid (and does nothing). But the program actually has a bug, since local variables are normally not initialised implicitly.
p = x;
This would make p contain same value as x ( p would point to same object as x). So basically when you say
delete p;
Its doing delete on the address referred to by p which is same as that of x. Hence this is perfectly valid as object referred to by that address is allocated using new.
Second case :-
Co-incidently your pointer p is set by compiler as a NULL pointer( You should not depend on this). So deleting that pointer is safe. Had that not been a NULL pointer you would have possibly seen a crash.
Ok, let's take a look at the documentation for the "delete" operator. According to http://en.cppreference.com/w/cpp/memory/new/operator_delete:
Called by delete-expressions to deallocate storage previously allocated for a single object. The behavior of the standard library implementation of this function is undefined unless ptr is a null pointer or is a pointer previously obtained from the standard library implementation of operator new(size_t) or operator new(size_t, std::nothrow_t).
So what happens is the following: you are calling the new operator, which allocates sizeof(int) bytes for an int variable in memory. That part in memory is referenced by your pointer x. Then you create another pointer, p, which points to the same memory address. When you call delete, the memory is released. Both p and x still point to the same memory address, except that the value at that location is now garbage. To make this easier to understand, I modified your code as follows:
#include <iostream>
using namespace std;
int main() {
int * x = new int; // Allocate sizeof(int) bytes, which x references to
*x = 8; // Store an 8 at the newly created storage
cout << x << " " << *x << "\n"; // Shows the memory address x points to and "8". (e.g. 0x21f6010 8)
int * p; // Create a new pointer
p = x; // p points to the same memory location as x
cout << p << " " << *p << "\n"; // Shows the memory address p points to (the same as x) and "8".
delete p; // Release the allocated memory
cout << x << " " << p << " "
<< *x << " " << *p << "\n"; // p now points to the same memory address as before, except that it now contains garbage (e.g. 0x21f6010 0)
return 0;
}
After running, I got the following results:
0x215c010 8
0x215c010 8
0x215c010 0x215c010 0 0
So remember, by using delete you release the memory, but the pointer still points to the same address. That's why it's usually a safe practice to also set the pointer to NULL afterwards. Hope this makes a bit more sense now :-)
Before the answers, you need to understand the following points.
once you delete a pointer, it need not be assigned with 0. It
can be anything.
You can delete a 0 or NULL without any harm.
Undefined behavior is one in which anything could happen. The
program might crash, it might work properly as if nothing happened,
it might produce some random results, etc.,
However, I called delete on p in the above program and it compiles.
Could anyone explain this to me? Why could I delete p?
That is because you assign the address of memory allocated by new via x. ( p = x;) x ( or p) is a valid memory location and can be deleted.
Now x is called a Dangling pointer. Because it is pointing to a memory that no longer valid. Accessing x after deleting is undefined behavior.
Could anyone please explain me this ? Why I could delete p since it has nothing to with x?
This is because your p is assigned with 0. Hence you are getting away with undefined behavior. However it is not guaranteed that your uninitialized pointer will have a value of 0 or NULL. At this point it seems to work fine, but you are wading through undefined behavior here.
delete/free keyword is used to empty the stored value from the memory location. if we dont use pointers we have the reassign the value to NULL or just let them go out of scope.
Be careful using pointers, if we go out of scope using pointers without deleting the value. It will create memory leak. because that portion of the memory block is not usable anymore. And we lost the address because we are in different scope.
I am wondering about the delete[] operator in C++. (I am using Visual Studio 2005).
I have an unmanaged DLL that is being called by a managed DLL. When I close this program after performing a few tasks while debugging, I am getting many (thousands?) of memory leaks, mostly 24 bytes - 44 bytes in size.. I suspect it might be due to a certain unmanaged DLL I have.
Anyway, from what I understand, if I have the following code:
char* pointer = new char[500]
/* some operations... */
delete[] pointer;
Then all the memory for it is freed up correctly, am I right?
What happens when I have the following code:
char* pointer = new char[500];
char* pointerIt = pointer;
/* some code perhaps to iterate over the whole memory block, like so */
for (int i = 0; i < 250; i++){ // only iterate halfway
*pointerIt = 0;
pointerIt++;
}
delete[] pointer;
The memory pointed to by pointer is deleted right? So it means that pointerIt is now not pointing to valid memory.. But that's ok because I can set both pointers to NULL, right?
Anyway, what happens now if I do this:
char* pointerFirstPosition = new char[500];
char* pointerIt = pointerFirstPosition;
for (int i = 0; i < 250; i++){ // only iterate halfway
*pointerIt = 0;
pointerIt++;
}
delete[] pointerIt; // delete the pointer iterator...
Will this code delete the memory block pointed to by pointerIt up to pointerIt +500? or will it delete the memory block pointed to by pointerFirstPos to pointerFirstPos +500?
Could this result in a memory leak?
Sorry for the long winded message, I'm trying to get my message across clearly.
Thanks,
kreb
First question set:
char* pointer = new char[500]
/* some operations... */
delete[] pointer;
Then all the memory for it is freed up
correctly, am I right?
right.
Second question set:
char* pointer = new char[500];
char* pointerIt = pointer;
/* some code perhaps to iterate over the whole memory block, like so */
for (int i = 0; i < 250; i++){ // only iterate halfway
*pointerIt = 0;
pointerIt++;
}
delete[] pointer;
The memory pointed to by pointer is
deleted right? So it means that
pointerIt is now not pointing to valid
memory.. But that's ok because I can
set both pointers to NULL, right?
The memory pointer holds an address to is fully delted yes. Both pointer and pointerIt hold an address to invalid memory. Each pointer is simply a variable, and every variable is independent. So both store their own address independent of each other. The dereference operator * will simply give you the variable at that address. The variable at that address is a different variable than the pointer variable.
Third question set:
You should be deleting only the address that was allocated, the whole array. You'll have undefined results if you try to delete a partial array. Could it result in a memory leak? Possibly, could it result in a crash? Possibly, could it result in ....? Possibly.
So only delete what you allocate. If you allocate an array then you delete with delete[] if you delete a type that is not an array you delete with delete.
Here is an eample of something that is fine just for clarity:
char* pointer = new char[500];
char* pointerIt = pointer;
//This is fine because you are deleting the same address:
delete[] pointerIt;
//The memory that both variables point to is freed, do not try to free again
check out boost::shared_ptr or boost::scoped_ptr and NEVER worry about this again.
This gives you a static & reference counted way to manage your memory.
http://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/shared_ptr.htm