Dangling pointers - c++

I have read that dangling pointers are bad as they point to location that is supposed to be free.But I don't understand why is that bad?So can you give me any example of disadvantages of dangling pointer.

Once you have a dangling pointer, two things are forbidden:
You are not allowed to dereference the pointer. The behaviour on doing so is undefined.
You are not allowed to read the pointer. It's as if the pointer is an uninitialised variable, or one you've just declared.
Few folk tend to fully grasp (2), and are surprised the first time they find out about this!
As such, dangling pointers can compromise program stability. And that's quite a disadvantage.

A dangling pointer is a pointer that points to a location in memory where there was an object but that object is already gone.
A dangling pointer is nothing useful or desirable, it rather describes that the pointer is completely useless and you probably have a logic error in your code.
Consider this:
int* x;
{
int y = 4;
x = &y;
}
*x = 42; // BOOOM !! Dont do this !! Undefined behavior !!
After closing the scope (}) the object x points to does no longer exists. x will not automagically be set to NULL or anything the like. There is no y at the memory location x was pointing to. The official terminology is that after closing the scope x has a invalid pointer value in C++ and in C the value of the pointer is indeterminate.
On the other hand, if you do not dereference x after y is gone, there is no problem. x is still a dangling pointer but you can simply assign something else to make it point to some object again:
int* x;
{
int y = 4;
x = &y;
} // <- x can be said to be dangling here, but who cares?
int z = 5;
x = &z; // <- x again points to an object

Dangling pointer is risky because once allocated memory has been freed, it can be reclaimed by other allocations.
Consider this example:
int main(int argc, char *argv[]) {
int *p = (int *) malloc(sizeof(int));
free(p);
*p = 5;
printf("%d\n",*p);
}
Once p is freed, there is no guarantee that 5 will be printed anymore. Also, If we write to p's address, we might be overwriting some other value used in another part of your program and trigger segmentation fault.

Related

Passing the pointers by refrence?

**So recently i came up with a question in an interview it was based on pointers**
void fun(int *p){
int q = 10;
p = &q;
}
int main() {
int r = 20;
int *p = &r;
fun(p);
cout<<*p<<endl;
}
*my question is
(1)Justify the result w.r.t the memory allocation like how this is happening?;
(2) how to pass this pointer variable by refrence (i wrote *&p in the parameter of void fun()) when i did it i observed that the p is printing a garbage value ,Now first i thought may be fun has different memory allocation and when it takes the address of q from fun function it address changes but that address in main function is pointing to some garbage value ,Am i right and please explain?
void fun(int *&p) {
int q = 10;
// here the object q began its existence
p = &q;
// here you pass the address of that object *out*
// of the function, to the caller
// here the object q ceases to exist
// question: does anyone have now-invalid pointers that
// pointed to that object?
}
You'll of course immediately see that yes, the caller of fun has a pointer that doesn't point to a valid object (objects that don't exist are by definition invalid). This is undefined behavior. Anything can happen.
Whatever you observe is just as good as what anyone else would observe :) I can make this code pretend to work, or pretend fail on almost any compiler - it's only a matter of arranging things in a certain way. That doesn't make the code any more valid, of course, and the notion of "working" or "failing" is meaningless anyway: the code is invalid, so as far as C++ is concerned, the discussion about the effects is invalid as well :)

C++ primer 5 edition: using get member to initialize another shared_ptr independent object

On C++ primer 5 edition. chapter 12. Dynamic memory.
shared_ptr<int> p(new int(42)); // reference count is 1
int *q = p.get(); // ok: but don't use q in any way that might delete its pointer
{ // new block
// undefined: two independent shared_ptrs point to the same memory
shared_ptr<int>(q);
} // block ends, q is destroyed, and the memory to which q points is freed
int foo = *p; // undefined; the memory to which p points was freed
In this case, both p and q point to the same memory. Because they were created
independently from each other, each has a reference count of 1. When the block in
which q was defined ends, q is destroyed. Destroying q frees the memory to which q
points. That makes p into a dangling pointer, meaning that what happens when we
attempt to use p is undefined. Moreover, when p is destroyed, the pointer to that
memory will be deleted a second time.
As I see q is not a shared_ptr but a built-in pointer thus it doesn't has a reference count. Normally he should say the temporary shared_ptr object and p instead. isn't it?
Also an I think this code wouldn't cause a Undefined Behavior! Because I've tried it and runs fine. Because as I guess an expression like:
{ // new block
// undefined: two independent shared_ptrs point to the same memory
shared_ptr<int>(q); // I think this will be removed by the compiler as an optimization.
}
Thus I think there is only one shared_ptr manages that memory. So it is safe I think. But if he wrote:
{ // new block
// undefined: two independent shared_ptrs point to the same memory
shared_ptr<int> q2(q);
}
Then this is what he might mean.
Thank you!
The presented code is indeed problematic and not showing what it was intended to show, but not because of some presumed compiler optimization...
The line:
shared_ptr<int>(q);
doesn't create a new temporary shared_ptr with q being a parameter sent to the constructor of the shared_ptr! It creates a shared_ptr named q.
So it is indeed a bad code example and the fix that you propose is correct.
However as mentioned in the comments, the philosophy of: it runs thus it is not undefined behavior is wrong.
Another fix for the code in the example could be to use curly brackets {} for sending q as a parameter for the temporary shared_ptr:
int main() {
shared_ptr<int> p(new int(42)); // reference count is 1
int *q = p.get(); // ok: but don't use q in any way that might delete its pointer
{ // new block
// undefined: two independent shared_ptrs point to the same memory
shared_ptr<int> {q}; // q is now a parameter to a temporary shared_ptr
} // block ends, q is destroyed, and the memory to which q points is freed
int foo = *p; // undefined; the memory to which p points was freed
}
One last note - the suggestion of giving a name to the shared_ptr inside the block doesn't really waive compiler optimization, as long as the actual object is not used the compiler may drop its creation. So if you want to make sure compiler optimization wouldn't happen you should go for:
int main() {
shared_ptr<int> p(new int(42)); // reference count is 1
int *q = p.get(); // ok: but don't use q in any way that might delete its pointer
{ // new block
// undefined: two independent shared_ptrs point to the same memory
shared_ptr<int> ptr {q}; // q is now a parameter to a local shared_ptr
*ptr = 42; // do something with ptr
} // block ends, q is destroyed, and the memory to which q points is freed
int foo = *p; // undefined; the memory to which p points was freed
return foo; // do something with foo
}

C++ Different types of pointers

in the following code I found that same pointer instruction crash the application in a situation while not in other situation.
#include <iostream>
using namespace std;
int main()
{
int *p;
*p = 50; //this instruction causes the crash
int* q = new int;
*q = 50; //this instruction executes ok
cout << "p:" << p << endl;
cout << "q:" << q << endl;
return 0;
}
I want to know why this is the case?
The first pointer is uninitialized. It doesn't point to a memory location that has an int value. So when you deref it on the next line, you get a crash.
The second pointer is initialized to an int that has an actual space in memory. So when you deref it, it finds the value held in that space.
int *p;
This pointer points to nowhere i.e not at any valid address of the process. That's why it crashes
int* q = new int;
Points to a valid address returned by new int, hence worked
I see you need some links to documentation:
http://en.cppreference.com/w/cpp/language/pointer
http://en.cppreference.com/w/cpp/language/operator_member_access
http://en.cppreference.com/w/cpp/language/new
http://en.cppreference.com/w/cpp/language/delete
http://en.cppreference.com/w/cpp/language/storage_duration
To wrap it up:
You can use the indirection operator (*) to return the object the pointer points to (dereference the pointer).
You can only access (read or modify) an object via a pointer, when the pointer actually points to an object (which by default they don't).
You can assign the address of an object to the pointer to let the pointer point at it.
You can use the address-of operator (&) to acquire the address of an object for assigning it to a pointer.
You can use the new operator to create a new object and return the address to it for assigning it to a pointer.
You must use delete to eventually destroy objects created using new.
When you use pointers, you alone are responsible for the validity of the objects your pointers point to. Don't expect the compiler to warn you when objects are leaked or accessed beyond the end of their lifetime. If you do it wrong, you might observe undefined behavior.
Smart pointers can help to keep track of object ownership and take care of proper destruction.
For further reading:
Can a local variable's memory be accessed outside its scope?
What does "dereferencing" a pointer mean?
Undefined, unspecified and implementation-defined behavior
What is a smart pointer and when should I use one?
https://ericlavesson.blogspot.de/2013/03/c-ownership-semantics.html
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#e6-use-raii-to-prevent-leaks

Why cant set pointers in functions

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

What does *new int mean?

Can someone help me with this question?
The memory allocated on line (*) below is not deleted.
void f() {
int z = *new int; // (*)
//...
}
Without changing the code on line (*), is there any way to avoid leaking memory? If so, how? If not, why not?
What I don't understand is, what does *new int mean? Specifically, what does adding the * beside new mean?
Also, what if instead of int z, we have int &z?
That line is the memory leak. It also makes no sense what so ever allocating an int int on heap and derefencing it (with *) before saving it's handle (address returned by new). So the only posible way to avoid the leak is:
return;
// your silly * line here
Without changing the code on line (*), is there any way to avoid leaking memory?
In real life, you would absolutely change that line - it's insane.
Assuming this is an intellectual exercise, then possibilities are:
Add return; before it, so the new never happens;
Override ::operator new to return a pointer that you can access by other means, such as a global variable.
What I don't understand is, what does *new int mean?
new int dynamically allocates an object of type int, and gives a pointer to that. * dereferences that pointer so that the object can be copied to initialise z. The pointer is not stored anywhere, so there is no way to access or delete the dynamic object afterwards.
Also, the initialisation of z from the value of an uninitialised object gives undefined behaviour.
Also, what if instead of int z, we have int &z?
z would be a reference to, rather than a copy of, the dynamic object. It would then be possible to fix the leak with delete &z. That would be an unidiomatic, confusing thing to do; don't do it in real code.
In general, avoid dynamic allocation and, when it is necessary, manage dynamic resources with RAII types, like containers and smart pointers. Raw pointers are error-prone, expecially when exceptions are thrown; anything else is a recipe for insanity.
That to understand this statement
int z = *new int; // (*)
it will be useful to split it logically.
At first there is called operator
new int
Take into account that the memory allocated by this call will not be initialized.
The result of the execution of the statement is some temporary pointer to int that is int *
Let;s name it as p.
In the next step this temporary pointer is dereferenced
*p
and this expression returns some garbage that the allocated memory has.
And this garbage are assigned to variable z.
So the code has no any sense.
At least it would be better to write something as
int z = *new int( 10 );
or
int z = *new int();
or
int z = *new int {};
that to initialize variavle z
Nevertheless in any case there will be memory leak.
The only method that I see to escape the memory leak is to write
int z = *std::unique_ptr<int>( new int() );
No, there's no way to not leak memory with that code, since the pointer returned by new is lost.
*new int means "allocate memory for an int, resulting in a pointer to that memory, then dereference the pointer, yielding the (uninitialized) int itself". I think this is undefined behavior.