C++ : Delete dynamic variable [duplicate] - c++

This question already has answers here:
c++ delete pointer issue, can still access data [closed]
(6 answers)
C++ pointer array is still accessible after delete[] is called [duplicate]
(1 answer)
Closed 1 year ago.
What is the diffrence between
{p = NULL ;}
and
{Delete p; }
When I executed this code:
int *p ;
p = new int;
* p = 4;
cout << *p; // = 4
delete p ;
cout << *p; //
In the last line, I expected to get a garbage value because the pointer is not pointing at the same location anymore, right? But instead I got the same value which is 4, how is this possible?

p = NULL; merely sets p to NULL, but does nothing to the memory that p was pointing at.
delete p; frees the memory that p is pointing at, provided that memory was allocated with new (as it is in your example).
In your example, trying to access *p after calling delete p; is undefined behavior, so anything can happen. p is still pointing at the same address it was before, delete does not alter p itself in any way, but the memory that p is pointing at is no longer valid. You happen to be seeing the old data that was stored in that memory, but only because it simply hasn't been overwritten yet. But it is still not permissible to access invalid memory for any reason. The actual memory be still be physically allocated by the underlying memory manager, but is logically inaccessible to your code, until it is reallocated again.

Related

Can a pointer returned by new have the same value as a deleted pointer returned by a previous use of new

Will both the cout statement always print the same value?
#include<bits/stdc++.h>
using namespace std;
int main(){
int* p = new int();
*p = 54;
cout<<p; // it displays the address of int in heap();
delete(p);
p = new int[4];
cout<<p; // it displays the address of first block of memory, of array in heap;
return 0;
}
Will both the cout statement always print the same value?
No. After the delete(p) the memory allocated by the first new expression is deallocated and therefore free to be reused for a later evaluation of a new expression, but there is no guarantee at all that it will be.
That you are reusing the same pointer variable p is irrelevant. It simply stores the address of the storage location returned by the new expressions. You could have used different pointer variables to store the addresses in the same way.
It is also irrelevant that you create a int in the first new expression and a int[4] in the second. Both of the new expressions happen to return a int* which can be stored in the same variable, but nothing would change about the above if you had used simply int in both, or had used completely different types and a pointer variable of type void*.
Will both the cout statement always print the same value?
No. The purpose of delete is to allow memory to be reused so it's possible that the next allocation returns a value just deleted.
But how new manages memory is unspecified.
For example it my be managing pools of different sizes so asking for space 4 integers may not be from the same pool as 1.
It may be that on your platform that simple program will always return the same value twice. But you should regard that as entirely incidental and not something useful.
Whilst in this simple case you may observe the same address assigned to p that is not generally the case. The allocator will allocate a block of memory on a first fit basis, and it is likely in this case that the first available block of the requisite size will be at the same address as the block just released.
If you were to change the example to:
delete(p);
volatile int* dp = new int[4] ;
p = new int[4];
cout<<p;
You will almost certainly observe that the pointer value of p is no longer the same. Moreover if you were to have:
int* p1 = new int[4] ;
int* p = new int[4];
int* p2 = new int[4];
cout << p1;
cout << p2 ;
cout << p ;
delete[] p ;
p = new int[Ox8000];
cout << p;
It is likely that the heap will be fragmented such that the second p allocation will not fit in the space released by the delete.
The delete does not remove the memory from existence, it rather marks the block as available for re-use, returning it to the heap (and coelesing it with adjacent free memory). What you are observing when you get the same pointer value is simple reuse of the space returned to the heap.

Basic dynamic memory allocation and delete triggers an asssertion failed

I am doing some reviewing of the basics of C++, and I have some troubles understanding why my code is triggering an assertion failed.
void fonctionPointeur(int a)
{
int* p = new int;
p = &a;
std::cout << p << "----" << *p << std::endl;
delete p;
}
int main()
{
std::cout << "Hello World!" << std::endl;
int a = 6;
fonctionPointeur(a);
}
The assertion failed that I'm triggering is always different, which leads me to think that the delete of p is accessing some unknown memory slot.
When I remove the delete p; or the p = &a; then everything work just fine.
It seems to me that I'm not supposed to delete p and that it will be delete at the end of the scope, but it's dynamic allocation it's not supposed to be the case...
What am I missing here ?
In this expression
int* p = new int;
you are assigning to p a memory block allocated by new.
In this expression
p = &a;
you are assigning to p the address of mere temporary, a copy of the original variable a (as you pass it by copy in fonctionPointeur), that temporary cannot be deleted.
This is to be specific, even if you passed it by reference (void fonctionPointeur(int &a)) the problem remains, you also can't delete it as wasn't dynamically allocated.
Moreover, because p is now pointing to a, you lost access to the memory previously allocated, you cannot delete it anymore, this is a memory leak.
It seems to me that I'm not supposed to delete p
This is either correct or not correct depending on which value you are referring to:
int* p = new int;
This is the first value that you give for p. You must delete the result of new int or else the memory leaks.
p = &a;
Here, you assign a new value for p, overwriting the old value. You must not delete the result of &a because it is a pointer to an object with automatic storage. If you do delete this, then behaviour of the program is undefined.
You must have deleted p before overwriting the value because the previous value will be lost. Otherwise since this is the only copy of the pointer, this overwriting of the value guarantees a memory leak.
and that it will be delete at the end of the scope,
a which p points to will be destroyed automatically and its automatic storage will be deallocated.
The dynamic object which p used to point to will not be destroyed automatically and its dynamic storage will not be deallocated.
P.S. It his hardly ever useful to dynamically allocate an int. I recommend avoiding unnecessary dynamic allocation.
P.P.S I recommend avoiding owning bare pointers.

What happens when I delete dynamic array? [duplicate]

This question already has answers here:
C++ delete - It deletes my objects but I can still access the data?
(13 answers)
Closed 5 years ago.
I made a dynamic array (example):
int *a;
a = new int[3];
a[0] = 10; a[1] = 20; a[2] = 30;
Than I create a vector which stores pointers:
vector<int*> pa;
pa.push_back(&a[0]);
After I deleted (freed) the memory with "delete[] a;", I can still access to the element, that I push_backed. (cout << *pa[0]; output: 10)
Why is this happen? When I "delete[] a", it only deletes the pointer to the elements, but the elements are still accessable?
Your statement about how delete[] works is backwards. It deletes the elements but not the pointer. Continuing to use the pointer after its contents have been deleted, as you're doing, is undefined behavior. This means that literally anything is allowed to happen if you do it, so you shouldn't do it. It's by pure luck that you can still access the elements now, and bad things will happen in the future if you do it.

Some basic pointer questions

I have a few silly questions (probably for most), it's less about 'how' do I do them and more about 'why' do they work this way? I know you are not supposed to ask multiple questions, but these are fairly small and related to one topic. Seems like it'd be a waste to separate them out.
I understand for the most part pointers, and the operators themselves. (Although I am curious why the * is called the de-reference operator, since isn't it referring to a reference of what it contains?)
I.e:
int x = 25;
int *p = &x;
So & makes sense, since *p is a place in the stack of type int that contains the address of x (which we know is 25).
So by saying *p are we 'referencing' the address of p which is pointing to the 25. Maybe it's just an English semantics thing? Maybe someone can explain why it's called 'de-reference'?
Take this valid code sample:
int *p = new int;
*p = 5
Simple enough, we're making a new place in the stack with the size of an int pointer (whatever that may be). p will contain some address that has a 5 for a value.
Thing is, I haven't actually declared anything that's storing a 5, so what the heck is p pointing to? I mean, this does indeed work, but I never made a int x = 5 or anything like that, and gave the address to p to point to? How does it even know?
p contains an address that points to something, but I never made that 'address' it's pointing to? Does the compiler just know to create another address somewhere else? (Sorry if this is a really stupid question.)
I was reading on here about some memory leaks on another question:
A *object1 = new A();
pretending A is a class first of all. Someone was saying the object1 stores the value of A. Isn't that incorrect? Doesn't object1 store the address of what new A() created and is pointing to it?
Because delete object1 deletes the pointer, which points to the new A() (but from the other question delete object1 would indeed be the correct syntax. So does that leave the new A() hanging out there? Or does it get automatically deleted? (As you can tell I'm a bit confused.)
If delete object1 does indeed delete what the pointer is pointing to and not the pointer itself, doesn't this just leave a dangling pointer?
Here
int x = 25;
int *p = &x;
* is not the dereferencing operator. It's part of the type of p. It basically says that p is a pointer.
Here
int *p = new int;
*p = 5;
The key is new int. It dynamically creates an int and returns it's address, so p now points to that address. *p = 5 (btw, here * is the dereferencing operator) modifies the value -- of that dymanically allocated int -- to 5
Indeed object1 holds the address of the newly created A. Since we're here we should clarify this: A is a (user defined) type. So it makes no sense to say that A has a value. Objects of type A have value.
delete p doesn't delete a pointer. It does 2 things:
Destroys an object created by a new-expression
Deallocates storage previously allocated by a matching operator new
The pointer isn't actually changed, i.e. it still points to the same address. Only now that address isn't allocated, i.e. can't be dereferenced anymore.
You can further refer to this SO answer - Static, automatic and dynamic storage duration to further understand objects, pointers, new/delete.
1: I'm not sure what you're implying when you say "which we know is 25". The address of x is not 25, rather that is the value of x. You do not set the address of x in a statment like int x = 25
But to answer your question, p is a reference, which is to say its value is an address. Accessing the value stored at the address p requires the *p, which dereferences the pointer.
2: You have allocated memory for p; you executed a new. You have allocated 4 (or 8) bytes of memory for a new integer on the heap, so p is pointing to a newly allocated block of memory. Saying *p = 5; tells the compiler to set the value stored at that address to 5.
3: Your assumption is correct; object1 does not store the value of a new A, rather points to a block of memory equivalent in size to aninstance of an object of size A.
delete object1; Does not delete the pointer. The pointer is simply an integer on the stack, rather it gives back the allocated memory for that pointer back to the system. A as you knew it is deleted, but the pointer still exists, and using it at this point is undefined behavior. You are correct in assuming you have a dangling pointer now, that is why you should always set deleted pointers to NULL.

Assign value to deleted object

I have a small homework problem.
The following code is given:
int * p;
p = new int;
*p = 5;
The question is: Why is it useless to do
p = 0;
delete p;
but usefull to do
delete p;
p = 0;
?
In my opinion, both is useless. If an object is deleted, no new value can be assigned.
I also get in both cases a Segmentation fault.
For Why it is useful for the following:
delete p;
p = 0;
Quoting from stroustrup's answer: Why doesn't delete zero out its operand?
Consider
delete p;
// ...
delete p;
If the ... part doesn't touch p then the second "delete p;" is a serious error that a C++ implementation cannot effectively protect itself against (without unusual precautions). Since deleting a zero pointer is harmless by definition, a simple solution would be for "delete p;" to do a "p=0;" after it has done whatever else is required.However, C++ doesn't guarantee that.
One reason is that the operand of delete need not be an lvalue. Consider:
delete p+1;
delete f(x);
Here, the implementation of delete does not have a pointer to which it can assign zero. These examples may be rare, but they do imply that it is not possible to guarantee that any pointer to a deleted object is 0.'' A simpler way of bypassing thatrule'' is to have two pointers to an object:
T* p = new T;
T* q = p;
delete p;
delete q; // ouch!
C++ explicitly allows an implementation of delete to zero out an lvalue operand, and I had hoped that implementations would do that, but that idea doesn't seem to have become popular with implementers.
If you consider zeroing out pointers important, consider using a destroy function:
template<class T> inline void destroy(T*& p) { delete p; p = 0; }
Consider this yet-another reason to minimize explicit use of new and delete by relying on standard library containers, handles, etc.
Note that passing the pointer as a reference (to allow the pointer to be zero'd out) has the added benefit of preventing destroy() from being called for an rvalue:
int* f();
int* p;
// ...
destroy(f()); // error: trying to pass an rvalue by non-const reference
destroy(p+1); // error: trying to pass an rvalue by non-const reference
Recall that deleting 0 is allowed. Therefore, when you do this
p = 0;
delete p; // Deleting zero is ignored
you throw away the old value of p (thus creating a memory leak), and then call delete 0, which is ignored.
When you do this, however
delete p;
p = 0;
you use the old value first (to de-allocate the int), and only then zero it out. This makes sense, because the old value of p becomes both useless and dangerous as soon as delete is executed.
This sets the pointer to null and then calls delete:
p = 0;
delete p;
It is like saying
delete 0;
I think what you are thinking is that it is setting the int that p points to to zero, but that would be done like this:
*p = 0;
p = NULL;
and
p = 0;
In the above case you are assigning value to the pointer and not to the object it points to.
Are one and the same. delete function is used to free the memory allocated dynamically to an object.
When you say
delete p;
p = 0;
It is like saying free the memory allocated to the pointer p and
then you are saying assign the pointer to NULL. Which is right.
In the other case when you do this
p = 0;
delete p;
You are saying assign the pointer to NULL first. Now the pointer p
is not pointing to any valid dynamically assigned memory. So later
when you say delete p the compiler cannot find any memory to free
and hence throws a segmentation fault.
In the first case, you are assigning the value of the POINTER p to be '0', not the value of the int that p points to. That's why it is both useless (will in fact cause a memory leak), and causes a seg fault when you try to delete from memory address '0'. EDIT - actually I just learned that the segfault is not caused by the 'delete 0', which is ignored according to the standard, so something else is causing that.
In the second case you are freeing the memory / object pointed to by p (which should be fine), and then assigning the pointer to have a value '0', which should also be Ok, so not sure why you are seg faulting there? In terms of usefulness, it used to be considered good practice to set free'd pointers to a null or '0' value so you can test for that before de-referencing them.