I was just a little confused why the same memory address was being printed when I attempted to delete a newly allocated variable through a function, I am guessing that no memory was leaked or pointer dangled.
The same memory address was printed.
#include <iostream>
using namespace std;
void deallocater(int *p)
{
delete p;
p = nullptr; // memory deleted and no dangling pointer right?
}
int main()
{
int *x = new int(1);
cout<<x;
deallocater(x);
cout<<endl<<x; // why is the same memory address being printed?
return 0;
}
I'm assuming that the function worked successfully
Calling the function
void deallocater(int* p)
{
delete p;
p = nullptr;
}
via
deallocater(x);
copies the value of x to p. Thus within deallocater() the local variable p is assigned nullptr. However, the variable x of the calling program is not altered.
You may achieve what you appear to want by taking the argument by reference:
void deallocater(int* &p)
{
delete p;
p = nullptr;
}
However, memory allocation and de-allocation should not be split apart into different and unrelated functions to avoid the danger of dangling pointers and/or memory leaks. Instead, good C++ code contains hardly any delete statements and few new statements (to initialize smart pointers), but instead use standard library constructs (containers and smart pointers) for memory management.
The code cannot change the content of the pointer p in deallocater(), thus it still shows the same value when printed. After the call p still has the same (pointer) value, but the memory it points to is freed. This is known as a "dangling reference".
To update the pointer, use a double-pointer, or a reference to a pointer:
void deallocater(int **p)
{
delete *p;
*p = nullptr; // memory deleted and no dangling pointer right?
}
int main()
{
int *x = new int(1);
cout<<x;
deallocater( &x );
cout<<endl<<x; // why is the same memory address being printed?
return 0;
}
Related
I want to create a class that contains a pointer, and upon initialization, the pointer can be dereferenced to give an integer assigned at initialisation.
This was my first attempt to write this code. This passed compiler and gave me the correct result without warning. However I later think this code has a potential problem.
That is in the constructor, the integer a is created on a stack framed to the constructor function. I am however making 'ptr' pointing to this stack memory address. The problem is this memory can be reused upon maybe calling other functions, so I might get garbage value if I am not lucky.
#include <iostream>
using namespace std;
class P {
public:
int *ptr;
P(int);
};
P::P(int a){
int *ptr = new int (0);
ptr = &a;
}
int main() {
P p(99);
cout <<*(p.ptr) <<endl;
}
A better way would be to create an integer variable on heap, copy the value of a to that variable, and make ptr pointing to that memory space on heap.
P::P(int a){
int *i = new int (0);
*i = a;
ptr = i;
}
Is my analysis correct?
Thanks!
The statements
int *ptr = new int (0);
ptr = &a;
are problematic, but probably not because of the reasons you think.
The reason it's problematic is because you define a new and distinct local variable ptr inside the function. This is not the same as the P::ptr member variable.
There's also a second problem, which is a memory leak. You allocate memory with new, but you never free the memory with delete.
If you really is required to use a raw and non-owning pointer to a single int value, I recommend you do it using a constructor initializer list:
P(int a)
: ptr{ new int(a) }
{
// Empty
}
Here new int(a) will create a new int value and copy the value of a into it.
Remember to then create a destructor which free's the memory you have allocated. And then you need to learn about the rules of three, five and zero.
To use the rule of zero, and to avoid memory leaks and make life simpler, use a smart pointer like std::unique_ptr:
struct P
{
std::unique_ptr<int> ptr;
P(int a)
: ptr{ std::make_unique<int>(a) }
{
}
};
And of course, since it's just about a single int value, and you don't need a reference to the original value, there's no need for pointers at all.
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;
}
I have noticed that if i create a pointer in a function, it won't let me set a value to it.
for example:
int func() {
int* pointer;
*pointer = 0 //error I get: "Exception: STATUS_ACCESS_VIOLATION"
return *pointer;
}
I get that not letting you set a pointer in the function because if I use a normal int it works:
int func() {
int notAPointer;
notAPointer = 0;
return notAPointer;
}
Can anyone explain to me why that is?
You haven't assigned any memory for your pointer to point to.
That means that dereferencing the pointer (*pointer) causes undefined behavior (like a crash in your case). You need to initialize the pointer before dereferencing it:
int* pointer = new int;
(And afterwards, delete pointer; to not leak the memory. Always delete everything you get from new.)
Also, pointers don't have to point to dynamically allocated data (acquired by a call to new), you can point to automatic (stack) variables too:
int func() {
int valueOnStack = 42;
int* pointer = &valueOnStack;
*pointer = 0;
return *pointer;
}
Because when you declare pointer it is pointing to a completely arbitrary memory location. You can't just write to any old piece of memory.
You need to allocate memory for it first:
int* pointer = new int;
*pointer = 0;
Or just:
int* pointer = new int();
The pointer pointer is uninitialized and points to a random location in memory when you declare it. It could be pointing into the system stack, or the global variables, or into the program's code space, or into the operating system. When you say *pointer = 0;, the program will simply try to write a 0 to whatever random location pointer points to.
The program may explode immediately, or may wait half an hour and then explode, or it may subtly corrupt data in another part of your program and you may never realize it. This can make this error very hard to track down. Make sure you initialize all pointers to a valid address before dereferencing them.
pointer does not point to anything following int* pointer;
So the behaviour of dereferencing it is undefined.
If you'd written
int n;
pointer = &n;
then you could dereference it.
Altenatively, you can allocate memory to it from the heap:
pointer = new int;
But you must remember to call delete pointer; else you'll leak memory.
This code is completely valid inside a function:
int *pointer = 0;
BUT, it would be the same as setting a pointer to the NULL macro.
If you try to set another value the compiler is going to complain that there is no valid conversion from int to int*:
int *pointer = 1; // Error
However, if you want to assign a value to the pointer, follow TartanLlama's answer using new and delete. Allocate memory first and then assign a value:
int *pointer = new int;
*pointer = 1; // OK
// delete when appropriate
#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.
Consider I have the function:
int &create_ptr(){
int *x = new int;
*x =5;
return *x;
}
int main(){
int y = create_ptr();
}
Will this cause a memory leak or is there somehow to delete it?
Sorry if it's a basic question, this has just been bugging me and I couldn't really find the answer.
Thank you everyone, makes sense now!
To satisfy your curiosity, yes you can delete it safely, but only if you return it by reference (pointer or C++ reference (&)). By reference so as to retain the original address of your newed object. You need that address for you to correctly and safely delete your object.
int& create_ref(){
int *x = new int;
*x =5;
return *x;
}
int* create_ptr(){
int *x = new int;
*x =5;
return x;
}
int create_sane_version() {
return 5;
}
int main(){
int& x = create_ref();
delete &x; // OK. Get address of x; same as deleting through a pointer pointing to its address
// x here refers to the newed object inside create_ref() (*x)
// Still begs the question of why you're painstakingly doing this
int* y = create_ptr();
delete y; // OK, but not optimal (the above isn't either)
// * not optimal == a bad way to do this
int leak = create_ref();
delete &leak; // DEFINITELY NOT OK. leak isn't the same as the newed object
// i.e. &leak != &create_ref();
// You're actually *copying* the object referred to by the returned
// reference. The returned reference gets lost.
int best_way_to_do_this = create_sane_version();
}
Will this cause a memory leak?
Yes, it will. You are allocating dynamic memory with the new statement with no corresponding delete to free it, ergo: you have a memory leak.
Is there somehow to delete it?
Of course there's: don't do dynamic memory allocation with naked pointers. In your case, why do you even need a reference at all?
int create(){
return 5;
}
int main(int, char*[]){
int y = create();
}
If you really need dynamic memory you can use std::shared_ptr and std::make_shared like this:
#include <memory>
auto create_ptr() {
return std::make_shared<int>(5);
}
int main(int, char*[]) {
std::shared_ptr<int> y = create_ptr();
}
Yes, this will create a memory leak. You allocate space with new, but never free it using delete.
If you want to create an object (or a primitive type) on the free store, you can return a pointer, and make the function caller for deleting the pointed-to object.
// Caller is responsible for deleting pointed-to int.
int* create_ptr()
{
// Hope that operator new does not throw std::bad_alloc
int* x = new int;
*x = 5;
return x;
}
A better approach would be to return a smart pointer, but that it outside the scope of this question.
Since you create memory on heap int *x = new int;, You need to explicitly delete it.
You can use shared pointers if you want to avoid track of all heap memory and deleting it explicitly.
Shared pointers keep track of all reference to a memory when last reference goes out of scope, memory pointed is deleted.