I have created one Node object and the pointer named head is pointing to it. Then another pointer named newHead is created which points to the same object. Then I delete the memory by doing delete head and reassign head to a nullptr. However, this change is not reflected by the newHead pointer. From the attached code it is evident that newHead is not a nullptr and accessing the member value returns garbage value.
To understand this problem, I have already gone through this post which states that
Also note that you can delete the memory from any pointer that points to it
which is evidently not the case for the attached code below. Further I know that using smart pointers will definitely one way to resolve the issue, but in my application, I do need to use a raw pointer.
Any help in giving me an understanding of why is this happening and how to resolve it will be appreciated. Thank you.
#include <iostream>
using namespace std;
class Node {
public:
Node(int value) {this->value = value;}
int value;
Node* next = nullptr;
};
int main(int argc, char** argv) {
// create a node object
Node* head = new Node(5);
// another pointer pointing to head
Node* newHead = head;
// delete the object pointed to by head
delete head;
head = nullptr;
// check if newHead is nullptr
if (newHead == nullptr) {
std::cout << "newHead is a nullptr" << std::endl;
}
else {
std::cout << "Head is not a nullptr" << std::endl;
std::cout << "Node value is: " << newHead->value << std::endl;
}
return 0;
}
The two pointers were pointing to the same memory, the nullptr is not put in there instead of the deleted object.
head = nullptr; // this is not putting nullptr where the deleted object was!
This is why, newHead is not pointing to nullptr but to a released memory.
What you want is a Reference to pointer
// CPP program to demonstrate references to pointers.
#include <iostream>
using namespace std;
int main()
{
int x = 10;
// ptr1 holds address of x
int* ptr1 = &x;
// Now ptr2 also holds address of x.
// But note that pt2 is an alias of ptr1.
// So if we change any of these two to
// hold some other address, the other
// pointer will also change.
int*& ptr2 = ptr1;
int y = 20;
ptr1 = &y;
// Below line prints 20, 20, 10, 20
// Note that ptr1 also starts pointing
// to y.
cout << *ptr1 << " " << *ptr2 << " "
<< x << " " << y;
return 0;
}
Output:
20 20 10 20
Credit to geeksforgeeks
In contrast, having
int* ptr2 = ptr1;
int y = 20;
ptr1 = &y;
Gives
20 10 10 20
If you delete the memory pointed by one or more pointers, the pointer values don't change. You can test this by checking the value pointer before and after the execution of the delete statement.
There's no way to (without saving some meta information somewhere) to know how many or what pointers are still pointing to some memory buffer.
The approach followed by this class of objects (that get pointed to from different places) is to have a count of the number of pointers you still have pointing to the buffer. When you assing a new reference, you increment the pointer, and when you delete one reference, you decrement it, and, only when the count of reference pointers is about to reach 0, then you actually delete it.
It's not complicated to use this technique to implement dynamic classes like trees or more abstract. I used it to implement a string type, years ago, with a copy on write semantics that allowed you to save copying string contents on mostly readonly strings.
I have created one Node object and the pointer named head is pointing to it. Then another pointer named newHead is created which points to the same object. Then I delete the memory by doing delete head and reassign head to a nullptr. However, this change is not reflected by the newHead pointer. From the attached code it is evident that newHead is not a nullptr and accessing the member value returns garbage value.
Right. Nowhere in your code in your code to you change newHeads value, so it still has the same value it had before. Of course, it is an error to access the member value because the object no longer exists.
To understand this problem, I have already gone through this post which states that
Also note that you can delete the memory from any pointer that points to it
which is evidently not the case for the attached code below.
Why do you say that? That's exactly what happened in your code. You had two pointers that point to the same block of memory and you could have used either to free it. You used one of them, and it was freed.
Any help in giving me an understanding of why is this happening and how to resolve it will be appreciated. Thank you.
You never change the value of newHead, so it contains the same value it had before you called free. Only after you call free, that object no longer exists, so it's a useless garbage value.
It's not clear what you don't understand. After you free a block of memory, it is an error to access it. The solution is simple -- don't do that. After you do delete head;, both head and newHead point to memory that is no longer allocated. You set head to nullptr, but you don't change newHead's value, so it still points to where the memory used to be.
If you are going to use malloc or new, it is your responsibility to track the lifetimes of objects and not access them outside their lifetimes.
Related
This question already has answers here:
Deleting C++ pointers to an object
(9 answers)
Why pointer is not NULL after using delete in C++
(2 answers)
Closed 4 years ago.
I've created a dynamic object in C++ using pointer. I set the value for the dynamic object. Then I delete pointer, but when I try to print the value of dynamic object, it is stay the same.
I have tried to print the value of pointer which is the address of the dynamic object, it is stay the same before and after I delete pointer.
#include<iostream>
using namespace std;
struct students
{
string name;
int agee;
};
int main()
{
students *p = NULL;
p = new students;
(*p).name = "Vu Trung Nghia";
(*p).agee = 20;
cout << p->name << " " << p->agee << endl;
delete p;
if(p == NULL)
cout << "It was deleted";
else
cout << (*p).name << " " << (*p).agee << endl;
}
I expect the result is: p == NULL or can't print "Vu Trung Nghia 20"
Actual result: "Vu Trung Nghia 20"
I expect the result is: p == NULL
There is no reason to expect that, since you never assigned p = NULL.
I have tried to print the value of pointer which is the address of the dynamic object, it is stay the same before and after I delete pointer.
This is the expected behaviour. Deleting a pointer has no effect on the value of the pointer.
but when I try to print the value of dynamic object, it is stay the same.
Behaviour of accessing a destroyed object is undefined. You don't ever want your program to have undefined behaviour.
When the behaviour is undefined, anything could happen. "I try to print the value of dynamic object, it is stay the same." is one of the possible behaviours.
So what deleting a pointer really is?
Assuming the pointer points to an object that was allocated with new, then delete destroys the pointed object, and deallocates the memory. Deallocation means that a subsequent new may re-use that memory.
delete frees the pointer from memory, it does NOT change its value or address, the value stays there, the calls which you do after deleteing it invokes Segmentation fault (which can easily be translated to your program having Undefined behvaior)...
This is the reason why people set the pointer to NULL after invoking delete...
delete p;
p = nullptr; // Stop memory leaking...
You will also find that you are no more able to modify the pointer:-
(*p).name = "Hello!"; /* Value is freed/destroyed from memory, cannot be
modified anymore... */
Or just overload your own delete operator:
struct students
{
string name;
int agee;
void students::operator delete ( void* ptr ) {
std::free(ptr);
ptr = nullptr; // Stop memory leaking...
}
};
I just learned pointer and delete pointer in class for C++. I tried this code by my own
# include<iostream>
using namespace std;
int main(){
int num = 10;
int *p = new int;
p = #
cout << *p << endl;
delete p;
cout << num << endl;
return 0;
}
After deleting the pointer p, I cannot print the value of num. But if I delete p at the very end of the program, cout << num << endl; will give me 10. Anyone knows where I did run?
You first leaked a pointer
int *p = new int;
p = # // You just leaked the above int
then illegally deleted something you did not new
delete p; // p points to num, which you did not new
You have already received a couple of good answers that point out the mistake, but I read a deeper misunderstanding of the allocation and deallocation of heap vs stack variables.
I realised this has become a pretty long post, so maybe if people think it is useful I should put it as a community Wiki somewhere. Hopefully it clarifies some of your confusion though.
Stack
The stack is a limited and fixed size storage. Local variables will be created here if you don't specify otherwise, and they will be automatically cleaned up when they are no longer needed. That means you don't have to explicitly allocate them - they will start existing the moment you declare them. Also you don't have to deallocate them - they will die when they fall out of scope, loosely speaking: when you reach the end brace of the block they are defined in.
int main() {
int a; // variable a is born here
a = 3;
a++;
} // a goes out of scope and is destroyed here
Pointers
A pointer is just a variable, but instead of an int which holds a whole number or a bool which holds a true/false value or a double which holds a floating point, a pointer holds a memory address. You can request the address of a stack variable using the address operator &:
{
int a = 3, b = 4;
int* p = &a; // p's value is the address of b, e.g. 0x89f2ec42
p = &b; // p now holds the address of b, e.g. 0x137f3ed0.
p++; // p now points one address space further, e.g. 0x137f3ed4
cout << p; // Prints 0x137f3ed4
} // Variables a, b and p go out of scope and die
Note that you should not assume that a and b are "next to" each other in memory, or that if p has a "used" address as its value then you can also read and write to the address at p + 1.
As you probably know, you can access the value at the address by using the pointer indirection operator, e.g.
int* p = &a; // Assume similar as above
*p = 8;
cout << a; // prints 8
cout << &a << p; // prints the address of a twice.
Note that even though I am using a pointer to point at another variable, I don't need to clean up anything: p is just another name for a, in a sense, and since both p and what it points to are cleaned up automatically there is nothing for me to do here.
Heap
The heap memory is a different kind of memory, which is in theory unlimited in size. You can create variables here, but you need to tell C++ explicitly that you want to do so. The way to do this is by calling the new operator, e.g. new int will create an integer on the heap and return the address. The only way you can do something sensible with the allocated memory, is save the address this gives you. The way you do this, is store it in a pointer:
int* heapPtr = new int;
and now you can use the pointer to access the memory:
*heapPtr = 3;
cout << heapPtr; // Will print the address of the allocated integer
cout << *heapPtr; // Will print the value at the address, i.e. 3
The thing is that variables created on the heap will keep on living, until you say you don't need them anymore. You do that by calling delete on the address you want to delete. E.g. if new gave you 0x12345678 that memory will be yours until you call delete 0x12345678. So before you exit your scope, you need to call
delete heapPtr;
and you will tell your system that the address 0x12345678 is available again for the next code that comes along and needs space on the heap.
Leaking memory
Now there is a danger here, and that is, that you may lose the handle. For example, consider the following:
void f() {
int* p = new int;
}
int main() {
f();
cout << "Uh oh...";
}
The function f creates a new integer on the heap. However, the pointer p in which you store the address is a local variable which is destroyed as soon as f exits. Once you are back in the main function, you suddenly have no idea anymore where the integer you allocated was living, so you have no way to call delete on it anymore. This means that - at least for the duration of your program - you will have memory that according to your operating system is occupied, so you cannot use it for anything else. If you do this too often, you may run out of memory even though you can't access any of it.
This is one of the errors you are making:
int* p = new int;
allocates a new integer on the heap and stores the address in p, but in the next line
p = #
you overwrite that with another address. At this point you lose track of the integer on the heap and you have created a memory leak.
Freeing memory
Aside from freeing memory not often enough (i.e. not instead of once), the other error you can make is freeing it too often. Or, to be more precise, you can make the error of accessing memory after you have told your OS you don't need it anymore. For example, consider the following:
int main() {
int* p = new int;
*p = 10;
delete p; // OK!
*p = 3; // Errr...
}
That last line is very wrong! You have just returned the memory allocated when you called delete, but the address is still stored in p. After you call delete, your OS is allowed to re-allocate the memory at any time - for example, immediately after another thread could call new double and get the same address. At that point, if you write *p = 3 you are therefore writing to memory that is no longer yours which may lead to disaster, if you happen to overwrite the location in memory where the nuke's launch codes are stored, or nothing may happen at all because the memory is never used for anything else before your program ends.
Always release your own memory, and nothing but your own memory
We have concluded the following: memory allocated on the stack is not yours to claim, and not yours to release. Memory allocated on the heap is yours to claim, but you must also release it once and only once.
The following examples are incorrect:
{
int a = 3;
int* p = &a;
delete a;
} // Uh oh... cannot clean up a because it is not ours anymore!
{
int* p = new int;
delete p;
*p = 3; // Uh oh, cannot touch this memory anymore!
delete p; // Uh oh, cannot touch this memory anymore!
}
Why does it print 10?
Well, to be honest, you were just "lucky" there. Actually, the way your operating system manages memory, is generally pretty lazy. When you tell it "I would like some memory" it doesn't zero it for you. That is why it is a bad idea to write
int main() {
int a;
a = a + 3;
cout << a;
}
You get allocated a variable a somewhere in the memory, but the value of a will be whatever was in that memory location. It might be zero, or some random number that depends on how the bits fell when you booted your computer. That is why you should always initialize the variable:
int a = 0;
Similarly, when you say "I don't need this memory" anymore, the OS doesn't zero it. That would be slow and unnecessary: all it needs to do is mark the memory as "free to be re-allocated". So if you give it back and access it immediately afterwards, the probability that it has not been re-allocated yet is pretty large. Therefore
int* p = new int;
*p = 10;
delete p;
cout << *p;
is not guaranteed to print 10. The address p is pointing to may have been (partially) taken (and initialized!) by someone else immediately after the delete. But if it hasn't, the memory will still contain the value 10 there so even though it isn't yours anymore, C++ will still allow you to access it. Basically, when you are using pointers, you are telling it "trust me, I'm a programmer - you don't need to do all kinds of slow checks to make sure I'm staying where I'm supposed to be, instead I'll be careful about that myself!"
using namespace std;
int main(){
int num = 10; // a) an int is created on stack
int *p = new int; // b) another int is allocated on heap
p = # // c) address of int from stack is assigned to p and the pointer
// allocated in b) is leaked: as nothing points to it anymore,
// it can't be deleted
cout << *p << endl;
delete p; // d) deleting a pointer that was not dynamically allocated
// and is pointing to stack.
cout << num << endl;
return 0;
}
Good day,
I just started to learn void pointers in c++ and now I'm writing binary tree where value stored in each node is void pointer to a value.
struct TreeNode
{
int count;
void* data;
TreeNode *left;
TreeNode *right;
};
The problem occurred in very first method-add method.
my method now takes int a a parameter and return nothing
At the very beginning i create new node.
To do that I need to cast integer into void.
Program compiles and first element adds to root correctly-however then when i send another number to method it stores in root again.
so if in main i have something like
tree.addToTree(12);
tree.addToTree(13);
than it would store 12 first and than right after else statement(code below)how that root->data i 13.
void Tree::addToTree(int num)
{
if(root==NULL){
root= new TreeNode();
root->data=#
//((int *)(root->data)) = num;//i tried to convert to void* in this way but it give me segmentation fault
root->left=NULL;
root->right=NULL;
}
else{
//here root value is already changed
int *intPtr = static_cast<int*>(root->data);
cout << "key2" << *intPtrT << endl;
//TreeNode* current= insert(num,root);
}
}
as i understood thats because i use &num so my parameter always tore in one place and a root is "connected" to &num it change as well.
I tried to find solution but was unsuccessful.
Is there a way to cat int to void pointer?
First of all, there are very very few reasons to store something as a void* instead of using a strongly typed method (e.g. template). Your entire problem goes away fairly quickly when you change your code to
template<typename T>
TreeNode
{
TreeNode<T>* left;
TreeNode<T>* right;
T data;
};
That said, the problem you have is that you are storing the address of a copy that will go away once the function goes out of scope:
if(root==NULL)
{
root= new TreeNode();
root->data=# // PROBLEM!!!
root->left=NULL;
root->right=NULL;
}
The problem line should be:
root->data = new int(num);
And you will have to properly delete the memory when you are done with it (e.g. when your tree is being destructed).
Alternatively, if you happen to be on a system where sizeof(void*) == sizeof(int), you can do this
root->data = (void*)num;
Which will simply treat the void* member as an integer. This does not work on systems where int is larger than void*.
First of all you should decide if you want to store data by value or by a pointer to it.
In first case having a pointer is just useless, you could use a template like:
template <typename T>
struct TreeNode
{
T data;
..
}
TreeNode<int> node;
This will work even with pointers (like T *data ... data = new int()).
In case you want to store a pointer to data you can also use a template with a type parameter or use a common ancestor class and then subclass it with the required types, eg:
class TreeData {
}
class TreeDataInt {
int value;
}
struct TreeNode
{
TreeData *data;
..
}
Lastly storying an int inside a void* pointer is something not so encouraged, using void* in C++ to achieve polymorphism is discouraged in general since you have many other tools which are safer and more reliable.
If you really want to store an int inside a void* then you should use the intptr_t type which is an integer that is convertible to a pointer. Eg:
#include <cstdint>
intptr_t value = 50;
node->data = static_cast<void*>(value);
intptr_t value2 = static_cast<intptr_t>(node->data);
This will save the value of the integer directly as an address inside the void*. This means that you can't dereference the pointer itself.
By the way root->data=&num is wrong since you are assigning to data the address of an automatic allocated variable which will become invalid when exiting its scope.
One problem I see is this (not the answer, just a problem)... in the function
void Tree::addToTree(int num)
{
if(root==NULL){
root= new TreeNode();
root->data=#
You are assigning the address of an automatic variable to data. The trouble is that as soon as the function exits, this variable will no longer exist (it is said to go out of scope) and so you have what's known as a dangling pointer, i.e., a pointer that points to an area of memory that is no longer used or is no longer used for the original purpose that the pointer expects.
You could fix this in three ways.
If you only want to store ints or any data type whose width is le that sizeof(void *), you could do root->data = (void *)num (note I cast the value of the variable to a void* and not the address of the variable). Or you could, as I see Zac has suggested too,
Create a copy of the variable and store the copies address. root->data = new int(num);. In this case you must make sure to delete the memory when you destroy the tree
Use templates as others have suggested (this is the better way) - I'll leave this point as others have covered it.
The other bit of you question where you have the comment
//((int *)(root->data)) = num;//i tried to convert to void* in this way but it give me segmentation fault
The reason this fails is because root->data at this point is just a pointer... it doesn't point anywhere (meaningful) yet. Thus when you try to dereference it, you are trying to access some memory that does "exist" yet (either pointer is NULL or has an invalid address), and so you seg fault.
When using a pointer in this way you need to create some memory and then make the pointer point to that memory, e.g. root->data = new int;. Once you have done that, you can then assign a value to that location in memory, e.g., *(root->data) = 1234;
This question already has answers here:
Function does not change passed pointer C++
(4 answers)
Closed 8 years ago.
so right now i am trying to do some nift code for a little game i am making and I've run into something that has been bothering me for a while about pointers.
but first things first, i am trying to have a function take in a void* and give that void* a value, but it seems to not actually stay beyond the function like i'm used to. so...
void ItemGen(void* Holder){
Item* NewItem
NewItem = new Item*
NewItem->Init();
Holder = NewItem;
}
it's not actually making "items" but various kinds of items that inherit from a item, this is just me making it simpler.
Holder gets changed but never make it outside the function, how should i change this, so that it does.
on top of that, i am sort of confused about a certain occurrence that can happen and i just want to know what happens when you do these. or really the difference between them
void *p1;
void *p2;
&p1 = &p2;
p1 = p2;
*p1 = *p2;
oh and is there a way to do a XOR operation on pointers so i can swap them with out a holding pointer.
i feel like i asked very stupid questions, but are confusing simply because they're void *'s.
Pointers are variables like any other, and as such are passed by value to functions. You've simply assigned a new value to the parameter copy of your pointer.
If you want to change a variable you pass to a function you must pass by reference or by pointer. Preferably the former.
void ItemGen(void *& Holder);
BTW, that's a horrible naming convention.
I am answering this point "Holder gets changed but never make it outside the function, how should i change this, so that it does."
void ItemGen(Item** Holder){
Item* NewItem
NewItem = new Item*
NewItem->Init();
*Holder = NewItem;
}
void someotherfunc() {
Holder * holder=0;
ItemGen(&holder)
if(holder!=0) {
holder->dosomething()
}
}
"void" simply means "nothing". A "void*" pointer points to nothing in particular. It's a way of saying "I don't know what kind of thing this pointer points to"; a void* pointer is a catch all that can receive any kind of pointer, but if you want to go from a void* pointer to any other kind, you have to explicitly cast it.
As to your first problem:
If you lived at "1234 Pointer Street", there is nothing magical about the number "1234", it's just a number. It only tells you anything when you treat it as a "pointer" - a house number. It "points" to a house on a particular street.
In the case of a computer, the street is memory.
int a = 0;
int* b = 0;
the variables "a" and "b" both contain the numeric value "0".
b = b + 1;
See? perfectly valid. So
void foo(int a, int* b)
{
a = a + 1;
b = b + 1;
}
void bar()
{
int x = 0;
int* y = 0;
foo(x, y);
// 'x' and 'y' are still zero here, they have to be, or you couldn't do
foo(0, 0);
}
Pointers to have some distinguishing features from regular variables.
int a = 0;
int* b = 0;
a = a + 1; // now a = 1
b = b + 1; // now b = b + sizeof(int) => 4.
What pointers do best is provide values for C/C++'s "dereference" operators.
a = *(b);
Going back to the streets example, if we assigned b our "1234 Pointer Street" address, it would be:
b = 1234;
What if we wanted to deliver something there?
*b
This means: The contents of the address that b describes.
Lets go back to the definition
int* b;
This says: "b is the address of an integer". How do we get the address of a specific integer?
// imagine a set of mailboxes.
int box1, box2, box3, box4, box5;
// lets put something interesting into box 3.
box3 = 5;
// now let's address somethign to box3.
// "&" is the "address of" operator.
int* pointer = &box3;
// now lets put something more interesting in pointer.
pointer = 10;
// whoops - that was wrong, we just changed the ADDRESS to some random numeric value.
// what we mean't was:
*pointer = 10;
printf("box 3 contains %d\n", box3);
// answer? 10, not 5.
After setting "pointer = &box3" we populated "pointer" with the location of box3's storage in memory, so when we wrote to that address using "*pointer = 10" we wrote to the storage address of box3.
You asked about
void *p1;
void *p2;
&p1 = &p2;
p1 = p2;
*p1 = *p2;
"&p1 = &p2" says "the address of p1 is the address of p2" and isn't legal, it wouldn't compile.
"p1 = p2" is legal, but it says "assign the same address as p2 to p1"
"*p1 = *p2" is illegal because you are using void pointers, which point to void, besides, you've just made p1 and p2 be equal to each other so it would be a null operation.
To fix your initial problem, you would need to provide a way for the caller to receive the new value you are creating.
Option 1: Accept a pointer-to-pointer
This is the very old-school C way to do it, but your code doesn't look very C++ so far so I'll list it first.
void ItemGen(void** Holder)
{
Item* NewItem = new Item;
NewItem->Init(); // why doesn't the constructor do this?
// ** means pointer to storage that is itself also a pointer,
// so if we dereference it once we will be refering to the inner pointer.
*Holder = NewItem;
}
Option 2: Return a pointer
void* ItemGen() // Why isn't this "Item*"?
{
Item* NewItem = new Item;
NewItem->Init();
return NewItem;
}
Option 3: Take a reference
void ItemGen(Item*& Holder)
{
Holder = new Item;
Holder->Init();
}
This says "Holder is a reference to a pointer to storage of type Item". It's exactly like a "Item*" pointer except instead of creating a temporary local copy of the value passed in, it's an alias for the value that was passed in.
If you absolutely have to throw away the type information of your pointer:
void ItemGen(void*& Holder)
{
Item* NewItem = new Item;
NewItem->Init();
Holder = NewItem;
}
At the level you appear to be with C++ so far, I would guess that your use of void* pointers is probably misguided.
Given the following code:
void Allocate(int *p)
{
p = new int;
*p++ = 2;
}
int main()
{
int i = 10;
Allocate(&i);
std::cout << i << std::endl;
}
I'm a bit confised about the meaning of:
*p++ = 2;
The output is 10 and my reasoning as to why this is the case is that *p++ is a temporary therefore any assignment to it is lost at the end of the scope of Allocate(int *p).
Is this the case?
Thanks in adv!
On input to Allocate, p points to the variable i in the main
function.
The address of this variable then lost and replaced by the
new int.
The value of this int (which is uninitialized and so could
start as anything) is set to 2.
The p pointer is incremented.
The Allocate function returns at this point, leaking the int that was
allocated.
The value of i in the main function is unchanged,
because Allocate did not modify it.
when you pass the the address of i into Allocate, another (temp) pointer is created that points to i's address (i.e. passing by pointer). then that temp pointer is pointed to a new location (via new int). thus the value of i is left alone.
p = new int;
You're assigning p new memory to point to instead of what it was pointing to before. You then change this newly allocated memory and it's lost forever when the function ends, causing a memory leak. If you remove the allocation line, it should cause an output of 2. The ++ does nothing in this case. It just increments the pointer and returns the old value to dereference.
As soon as you enter Allocate, you assign p to point to a new block of memory, so it no longer points to i. Then you modify that new block of memory (which is then leaked when the method returns.) i is unaffected because you've moved that pointer before you set the pointed-to memory cell.
void Allocate(int **p)
{
*p = new int;
**p = 2;
}
int main()
{
int j = 10;
int *i = &j;
std::cout << i << std::endl;
Allocate(&i);
std::cout << i << std::endl;
}
Output is :
10
2
You need a pointer to pointer to change the address of the location being pointed to.