Basic dynamic memory allocation and delete triggers an asssertion failed - c++

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.

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.

Delete dynamically allocated memory after swapping its pointer

I'm relatively new to C++ and I want to understand memory management and pointers at the same time.
Let's say I have the code below
int* p1;
int* p2;
int* p3 = new int[some size];
p1 = p3;
std::swap(p1,p2);
How do I properly delete the dynamically allocated memory? Is doing delete[] p3 enough? Should I delete p2 too after that?
There is some fuzzyness in colloquial speech when you do something like this:
delete x;
We say "we delete x". Strictly speaking thats wrong, because what is deleted is the object pointed to by x.
Every object allocated via new/new[] must be destroyed via one call to delete/delete[]. Whether you have two or more pointers to the same object does not change that.
int* p1 = nullptr;
int* p2 = nullptr;
int* p3 = new int[some size]; // p3 points to the array
p1 = p3; // p1 points to the same array
std::swap(p1,p2); // now p1 == nullptr, p2 points to the array
Note that the pointers are uninitialized in your example. Reading their values causes undefined behavior. As this isnt the crux of the question I avoided that by initializing them.
There is one array created via new [] and it is that one array that you have to delete via delete []. You may not delete it twice. So either call delete[] p3; or delete[] p2;, but not both.
PS: Comments already mentioned smart pointers and I also suggest you to read about them. Nowadays you should not use raw owning pointers. An owning pointer is one that you need to call delete on, it "owns" the pointed to object. Raw pointers should only be used to "observe", ie you should never need to worry about calling delete (or delete[]) on a raw pointer. Of course you still need to take care whether the pointed to object is still alive, but that is not specific to dynamic allocation:
int* p;
{
int x = 42;
p = &x; // p points to x;
} // x goes out of scope
// here p is not a valid pointer anymore
To understand what is happening here, it would help to add some debug statements, i.e:
std::cout << p1 << " " << p2 << " " << p3 << "\n";
The trace will result in an output like:
0 0 0x15e7eb0
0x15e7eb0 0 0x15e7eb0
0 0x15e7eb0 0x15e7eb0
(Note that I initialized p1 and p1 to nullptr)
p3 initially points to some memory. After the assignment p1 = p3, p1 now points to the same memory address as p3. When you swap the pointers, now it's p2 that points to the same memory address as p3.
There are a couple of things to note here:
You must pair delete[] with the corresponding new[] (do not call delete with new[] and so forth)
Calling delete on an already deleted object is undefined behavior
Calling delete on a null pointer is perfectly safe
As you can see, dealing with raw pointers and memory allocation can easily lead to pitfalls. It's generally recommended to use smart pointers, or if you have a non-owning pointer, to use abstractions like observer_ptr to clearly indicate the pointer's purpose in the code.

How to delete a pointer before return it in a function?

If we have a function like this:
int* foo()
{
int *x;
x = new int;
delete x;
return x;
}
We need to return a pointer in a function, but what we have learned is we need to delete a space in the final.
If we delete x first as above, then is it meaningful to return x in the final line? Because the x does not exist anymore.
But if we don't delete x before return, the function will be finished.
How can we do?
Or we don't really need to delete a space which was allocated in the memory?
You do need to delete the pointer at some stage, but that does not have to be in the same function scope where you new it. It can happen outside of your function, which I think is what you're trying to achieve.
int* foo()
{
int *x;
x = new int;
return x;
}
int *px = foo();
// use px in some way
delete px;
if we delete x first as above, then is it meaningful to return x in
the final line? because the x does not exist anymore.
Two things here, first no it is not meaningful to return x after delete x; and secondly, deleting x won't delete the x itself, it will only free up the memory to which the x points to.
or we don't really need to delete a space which was allocated in the
memory?
Wrong. You need to free up every dynamically allocated memory location.
but if we don't delete x before return, the function will be finished.
how can we do ?
What you can do is declare the pointer outside the function and then after you have returned the pointer x from the function, then you can delete it anywhere outside that function which returned the pointer.
Tip:
Consider using Smart Pointers because along with other benefits, one of the biggest benefit of using Smart Pointers is that they free up the allocated memory automatically and save you the headache of freeing up the memory explicitly.
There is absolutely no reason at all to delete the pointer before returning it. The only thing you will get is the memory address to a piece of memory that was allocated but no longer is.
It would make sense in this code:
main()
{
int *ptr = foo()
cout << "The memory address that function foo got "
<< "allocated to a local pointer is " << ptr << endl;
}
But come on, who would ever want to write such a thing?
It is, however perfectly ok to delete after the function call, like so:
int* ptr = foo();
delete ptr;
What you need to understand is that delete does not remove a pointer. What it does is to say "I (the program) am done with whatever this pointer is pointing to. You (the os kernel) can use it for anything now. I will not do anything more with that address. I promise." to the operating system. You do not have to have one delete for every pointer. This is completely ok, and causes no memory leaks:
int *p=new int;
int *a[3]={p, p, p};
int n;
cout << "Via which pointer in array a do you "
<< "want to delete the allocated memory? ";
cin >> n;
delete a[n];
It is pretty silly code, but it shows my point. It is not about the pointer. It's about what the pointer is pointing at.
And remember one thing. A pointer does not get the value NULL when you delete it. You have to take care of that separately.
Variables declared in the scope (between the {} ) of the functions are distroyed when leaving the function, as they are built on the stack memory of the function.
When using new(), memory is allocated on the heap, another memory space independant from the function.
This memory won't be freed before you delete the pointer pointing this memory, that's why once using a new(), you'll have to get the pointer deleted before your app returns.
Returning a deleted pointer doesn't make sense unless you want your application to crash. Dereferencing (accessing) a deleted pointer can lead to application crash or memory corruption.
If the purpose of your function is to provide a valid pointer on some type,
the delete will have to occur outside of the function, once you wont need to use the variable anymore.
Two last tips:
don't delete a pointer twice, this would cause a crash.
assigning 0 to a deleted (or non allocated) pointer can be a guard:
ex:
int * pt = 0;
pt = new int;
*pt = 12;
delete pt;
pt=0;
if (pt==0) {
// the pointer doesn't point to anything, and we can test it safely
}
/* ... */
if (pt!=0) {
delete pt; //this second delete wont occur if pt is null (==0)
pt=0;
}

What happens, when changing ptr which is pointing to allocated memory using operator new to some other memory?

#include <iostream>
using namespace std;
int main()
{
int a = 10;
try
{
int *p = new int;
cout<<"p is pointing to address:"<<p<<endl;
cout<<"Value at *p:"<<*p<<endl;
p = &a;
cout<<"a address:"<<&a<<endl;
cout<<"p is pointing to address:"<<p<<endl;
cout<<"Value at *p:"<<*p<<endl;
delete p;
cout<<"a address:"<<&a<<endl;
cout<<"a val:"<<a<<endl;
}
catch(bad_alloc &e)
{
cout<<e.what()<<endl;
}
return 0;
}
In the above example, the address pointed by p is changed to &a. By calling delete, logically the referent of p (deleted the thing pointed to by p) as p is pointing to address of a, now the a's address should be released to the heap.
I m curious to know about,
1. what will happen to the memory allocated by new? will it result in memory leak?
2. Even though this seems to be silly, (any way no harm in registering my thoughts) Will the compiler have any knowledge about the address pointed by p and delete exact address allocated by operator new?
In your example when you do delete you are trying to delete
a stack variable which will give undefined behavior.
The original int that p pointed to is lost and is leaked. That piece of memory will remain lost until the program exits.
The compiler doesn't keep tabs on your memory or any other runtime
functions, it just translates your program (your wishes) to machine code.
You know that this:
int *p = new int;
will allocate memory for an integer on the heap and it's address will be stored in p.
Now, when you say this:
p = &a;
that address is overwritten by the address of a i.e. p now contains the address of a and the address of the integer allocated on the heap is gone.
That memory is now leaked.
When you say:
delete p;
it is dangerous because p points to a variable on the stack.
And here is why you should not do that.
Credit of the link goes to chue x for his comment.

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.