Given this little piece of code :
#include <iostream>
#include <assert.h>
using namespace std;
struct Foo
{
// something
};
int main()
{
Foo *p1 = new Foo;
Foo * p2 = p1;
assert(NULL != p1);
delete p1;
p1 = NULL;
assert(NULL != p2);
delete p2;
cout << "everything is cool!" << endl;
return 0;
}
When I delete p1 , the second assert (assert(NULL != p2);) is not failing , why ?
The output : everything is cool!
Then why the assert of p2 is not failing ?
When I delete p1 , the second assert (assert(NULL != p2);) is not
failing , why ?
Deleting p1 or assigning to it has no effect on p2 itself. After you delete p1, p2 still points to that address, i.e. to a defunct object. It becomes a so-called dangling pointer. Of course, accessing it or deleting it (which you're doing) is undefined behavior.
Watch the stars, in particular.
int i;
int *p1 = &i;
assert(p1 != NULL);
int *p2 = p1;
assert(p2 != NULL);
*p1 = 10;
assert(i == 10);
assert(*p2 == 10);
p1 = NULL; // does not affect the object p1 was pointing at
assert(i == 10);
assert(*p2 == 10);
assert(p2 != NULL); // (which we already know, if the previous assert didn't crash)
You're right to suspect that everything is not cool. The program invokes the delete operator twice on the same object (a "double free" error), which will tend to corrupt the heap. If the program continued, you would see undefined behavior at some point. Having undefined behavior rather defeats the point of writing a computer program. If you want to see errors like this immediately and unambiguously, run it under valgrind's memcheck or equivalent.
One of the biggest and most confusing-to-beginners misnomer in C++ is the term "deleting a pointer". This has undoubtedly originated from the fact that a delete expression takes a pointer as its argument:
T * p = new T; // #1
delete p; // #2
However, what's really going on is that line #1 creates a new, dynamic, unnamed object. Think about this again: There is no variable whose value is the object create in line #1. The object is really out of reach, as indeed it does not live in any scope. All we have is a pointer to it.
To end the lifetime of a dynamic variable, we have to use a delete expression. But since we already know that we can only ever really have a pointer the object, not the object itself*, the expression conveniently accepts a pointer to the object we're deleting.
So really we should say that in line #2 "we are deleting the object *p by giving a pointer to it to the delete expression" (namely &*p == p).
The pointer itself is entirely unaffected by the delete call.
*) Yes, we could also have a reference variable, like T & r = *new T;, but that would be insane.
delete p; doesn't affect p. It destroys the object that p points to and frees its memory. p still has the value that it had before.
Related
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.
I have seen many pages for this error, but I'm not able to grasp what I'm doing wrong with my code, so I was hoping if I posted it, someone could shed some light.
This is a c++ class project. The goal is to write a function that takes two C strings (char*) and returns them concatenated together in a new. What I have here compiles, except for when I try to delete copycat, I get the malloc error in the title of this question.
How can I delete copycat?
I think I should be also deleting the "unused" news I created in the cat2 function (p, q), but that gives me the same error. What am I missing here with deallocating memory?
char* cat2(char* dest1, char* str2)
{
char* p = new char[100];
char* q = new char[100];
char* rvalue = new char[100];
for (p = dest1; *p != 0; p++)
{
;
}
for (q = str2; *q != 0; p++, q++ )
{
*p = *q;
}
*p = 0; /* set the last character to 0 */
rvalue = dest1;
return rvalue;
}
void main()
{
char s1[] = "Hello";
char s2[] = ", World!";
char* copycat = cat2(s1, s2);
cout << copycat;
delete copycat;
}
rvalue = dest1; makes rvalue point to what dest1 is pointing to. This is the local buffer s1 inside main.
So calling delete copycat; is the same as trying delete s1; which fails because it was not allocated via new. (and because it should be delete[]).
You make the same mistake with p = dest1; and q = str2;. These make p and q point to those buffers. You leaked all the memory you allocated via new, and caused a buffer overflow by writing characters past the end of s1.
I guess you intended to copy characters into the buffers you allocated via new. However, p and q buffers are useless anyway; you should be copying characters into the buffer pointed to by rvalue. To do that you will have to work with *rvalue and so on (which means: the location being pointed to by rvalue, instead of making rvalue point somewhere totally different and leaking memory).
So I'm having a bit of an issue, and need help with this beginner question.
I've changed my example so that it makes sense. I should not have posted one while sleep deprived.
I'm trying to copy a pointer (lets call it p1) in order to create a second pointer (lets call it p2).
When p1 changes the object it is pointing at, I don't want p2 to change along with it, which is what appears to be happening in my program.
Essentially, here is the issue I'm having....
#include <string>
#include <iostream>
int main(){
std::cout << "Pointer Test\n\n";
int num1, num2;
int * p1, * p2;
num1 = 5;
num2 = 10;
p1 = &num1;
p2 = p1;
std::cout << "P1 is pointing at value " << *p1 << " (should be 5)\n";
std::cout << "P2 is pointing at value " << *p2 << " (should be 5)\n\n";
*p1 = num2; //Even though the value of P1 is changing, I don't want the value of P2 to change. I want it to stay on num1
std::cout << "P1 is pointing at value " << *p1 << " (should be 10)\n";
std::cout << "P2 is pointing at value " << *p2 << " (I want this to be 5, not 10)\n";
return 0;
}
/*
Assignments I've tried to make this work...
p2 = p1; //didn't work - *p2 changes when *p1 does, which I am trying to avoid
*p2 = *p1; //didn't work - caused segfault
*p2 = p1; //didn't work - can't convert int to *int, so won't compile
p2 = &(*p1); //didn't work - gave same result as p2 = p1
*/
Any enlightenment on this matter would be greatly appreciated.
I think you have a misunderstanding of what is going on. The statement *p1 = num2; is not changing the value of p1, it is changing the value of whatever p1 points to. Since both p1 and p2 point to the same variable when you change its value through one pointer you will see the same value when you dereference either pointer. What you want to do is have p1 point to num2, not take the value of num2 and store it in whatever p1 points to.
Change
*p1 = num2;
to
p1 = &num2;
Consider the following code:
int a = 5, b = 10, *foo, *bar;
foo = &a; // foo now points at the address of A
bar = foo; // bar now points at the address at which foo is pointing
foo = &b; // foo now points at the address of B
cout << *foo; // prints 10
cout << *bar; // prints 5
Thats the behaviour you want to achieve if Im not mistaken.
Your code is nonsensical however. IF I'm not wrong, your mistake is that you create a second pointer which points at the address of the first pointer instead of pointing at the address from the first pointer.
Your first code makes no sense. If testObj isn´t a typedef to a pointer,
the * in the first p1 assignment is wrong (it should be &), and the second p1 assignment is wrong too, because you can´t assign a temporary object to a pointer, (only addresses to variables or from new).
And always remember to assign an address to a pointer p before using *p
If you want to copy pointers, the copy will point to the same thing as the original one and p2 = p1; is correct. If you want to copy objects, the pointer thing has nothing to do with it, and how the object is copied should be defined in a copy constructor and operator=.
Depending on the class, memcpy can work or not, don´t rely on it for such cases.
Nonsensical code aside
When p1 changes the object it is pointing at, I don't want p2 to change along with it
If p1 and p2 point to the same object, changing the object p1 points to will change the (same) object p2 points to, period. You'll have to use a different mechanism than raw pointers to avoid that behaviour. Like making copies of the object pointed to instead of copying the pointer.
Also
Do I have to use memcpy? Or is there another way?
Since this is C++, I'd avoid memcpy.
Defining a copy constructor or assignment operator is a better way of copying objects.
There is no type like obj *. The "*" binds tighter to "p1". So you need to change the decl from
obj * p1, p2;
To
obj *p1, *p2;
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.