Pointer to deallocated location Is it a Undefined Behavior? - c++

Pointer to deallocated location Is it a Undefined Behavior?
http://ideone.com/Qp3uY
int *p = new int;
*p = 10;
delete p;
*p = 10;
cout << *p << endl;

There mere existence of a pointer to a deallocated location is not undefined behavior in itself. Attempting to dereference that pointer does produce undefined behavior though.

Dereferencing a deleted pointer is an undefined operation. Don't do it.

This is undefined behavior:
If the argument given to a deallocation function in the standard library is a pointer that is not the null pointer value, the deallocation function shall deallocate the storage referenced by the pointer, rendering invalid all pointers referring to any part of the deallocated storage. The effect of using an invalid pointer value (including passing it to a deallocation function) is undefined. - C++ '03 3.7.3.2

When you allocate memory to make a new pointer, as you do in the first line
int *p = new int;
You're asking the operating system to produce some memory for you to use, for as long as you like. You can then put something in that spot, as you then do
*p = 10;
This memory is available for you to use as long as you want, and then you can tell the operating system you're done with it, by calling delete, as you do on the next line.
delete p;
The operating system now has the memory available to it, but it may or may not do something with that memory. If you allocate a bunch of other memory, it is possible that the new memory range includes this memory. The operating system may give away this memory to something else, or it may not - it's not going to tell you, that's why it is said to be undefined behavior to still use that place in memory.
*p = 10;
You then reuse this place of memory to set it to 10 again. Nothing else has happened in the meantime and this is a rather trivial program, so the operating system hasn't done anything else with that block of memory yet, so setting it in this case does not have any greater effect.
cout << *p << endl;
Again, the operating system owns the memory right now, but it isn't likely doing anything with it at this point; it's like staying in a hotel room after your stay is officially over. You may or may not be able to stay there, as you don't know whether the room is being used by another person afterward or if it is remaining empty. You could be thrown out, or you could be safe.

Related

Deleting Pointers

I wanted to ask, is dynamically creating a pointer, and then changing a pointer address to something else still deleting the original allocated space?
for example:
int main()
{
int c = 50;
// Memory leak
int * q = new int;
q = & c;
delete q;
}
What exactly is getting deleted or happening?
Thanks!
What exactly is getting deleted or happening?
Memory leaking and undefined behaviour.
When you do q = & c; you are losing your only tracking of the memory allocated by new int. Noone keeps track of this for you, there is no garbage collector, it is simply lost and cannot be recovered.
When you then do delete q; (where q is assigned to &c) you are deleting memory that you didn't allocate, and worse you are deleting memory on the stack. Either of these will result in undefined behavior.
This is an excellent preface into why you should avoid using pointers in circumstances where you don't need them. In this case, there is no reason dynamically allocate your int. If you really need a pointer, use a c++11 smart pointer (or boost if you don't have c++11). There are increasingly rare cases where you really do need a raw c type pointer. You should read Effective Modern c++ Chapter 4 for excellent detail on this subject.
is dynamically creating a pointer, and then changing a pointer address to something else still deleting the original allocated space?
No. delete will deallocate the memory to which its operand points. You must delete the same block of memory that you obtained from new.
int c = 50;
int * q = new int;
int * r = q;
q = & c;
delete q; // WRONG! q points to something you didn't get from new
delete r; // OK! p points to the block you got from new
To be even more clear, delete doesn't care about what variable it operates on, it only cares about what that variable points to. In the last line above, r points to the block that was originally pointed to by q and allocated by new, so you can safely delete it. q points to statically allocated memory, not something you got from new, so you can't delete it.
Instead of changing where q points, though, you can copy the value you want into the space that q points to:
int c = 50;
int * q = new int;
*q = c;
delete q; // OK! q still points to the same place
Here you're changing the value stored in the location to which q points, but you're not changing q itself. q still points to the block you got from new, so it's safe to delete it.
You code will (try to) delete c. There's no memory management or anything like that in C/C++. delete will try to delete whatever the given pointer points to, and and whatever is not deleted (either by calling delete for variables created with a call to new, or by leaving the scope for local variables) will remain in memory until the program ends.
Notice that trying to delete a local variable will propably cause a crash, since delete actually checks (in a very basic manner) what it deletes - at least to know how much memory has actually been allocated at that address. And at this check, it will propably notice that c doesn't include this information, or that it isn't even at the right end of the memory space, so it will crash.
It will crash because c is created in the stack memory section. If you're lucky and the program didn't crash you aren still leaking memory because the q reference is lost.
First answer is to your question:-
I wanted to ask, is dynamically creating a pointer
We don't create a pointer dynamically. Pointers are just a variable like other variable in C and C++. Difference is, pointer is a variable which can store the address of a particular memory location. In run time you just dynamically allocate memory and assign the address of first address location of that memory size into it.
Now what will happen if you don't delete/free the memory and assign a new address to it. In that case memory will not be release/freed and that can not be use anymore as that will never be marked as free by OS. When you free/delete memory O/S mark that area as free to use, and your running process can utilize it in future. That is call proper memory management. Improper memory manage leads your program to memory leak.

state of pointer if memory is deallocated

Say I have a pointer char* ptr allocated memory and another pointer char* arr = ptr
What happens to arr after ptr memory is deallocated.
Let the function be:
char* foo()
{
char* ptr = new char [100];
char* arr = ptr;
delete [] ptr;
return arr;
}
Can I use this returned value?
Will it cause any compile-time/Run-time error?
Or any thing else.
Or what would happen if the function was
char* foo()
{
char* ptr = new char [100];
char* arr = ptr;
delete [] arr;
return ptr;
}
I guess there would be no change from previous output but would there be any change??
What would happen If I have a class
class Pointer
{
public:
char* ptr;
Pointer()
{
ptr= new char [100];
}
~Pointer()
{
delete [] ptr;
}
};
and function
Pointer foo()
{
Pointer ptr;
ptr.ptr[0]='l';
return ptr;
}
Wont destructor be called at the end of the function and create a dangling pointer Pointer::ptr ??
Can I use this returned value??
You can "use" it, but you can't dereference it. You could, for example, print the pointer value out (but not the pointed-to data!):
std::cout << (intptr_t)foo() << std::endl; // OK
std::cout << foo(); // WRONG: this dereferences the pointer!
So while the value can be "used", it's not really useful as a pointer to char anymore.
Or what would happen if the function was [...]
Both functions have the same meaning. On any decent compiler, you should expect both to yield identical machine code when compiled.
What happens to arr after ptr memory is deallocated?
Nothing happens to it: its value remains unchanged. But because the pointed-to object has been deallocated, it is now a dangling pointer. So you can't use it for anything: if you do, you'll get undefined behavior. Undefined behavior means that anything can happen. This includes: nothing happening (things "appear" to "work OK"), or getting your hard drive formatted.
The situation is the same is if you built a house on a lot. You give your friend Arr the GPS coordinates. But in the meantime you decided to move out. Yet your friend Arr still has the old coordinates. Now Arr decides to use them. There are several possible outcomes - and you have no control over which one happens. I'll list just a few:
You moved out an hour ago. Everything is still the same. Arr stopped by, took a picture of your old home, and left.
This corresponds to a case where due to a coincidence, the pointed-to memory still contains usable contents. You still have a bug, but coincidence hides it.
You moved out, but the next day the city decided to raze the lot and build a big condo building on it and adjacent lots. Your friend comes in expecting a small house, sees a big condo high-rise and ends up completely stumped.
This corresponds to a case where the memory gets reused followed by the dangling pointer dereference. Whether this leads to CPU raising an exception or not depends on what kind of an object lived there before.
You moved out, but there was an earthquake and there's now a lake there. Your friend falls in and drowns.
This corresponds to a case where a now-redundant chunk of virtual memory that used to be a part of the free store has been unmapped. You get a page fault.
The memory manager runtime can deallocate the page that used to back the address space pointed to by your pointer. Recall that often a C++ program runs on top of a virtual memory machine. The address space seen by the program is the virtual address space. When there's no physical memory page backing a given virtual address space page, and no file or other backing for that page, any accesses to it will cause a page fault that propagates to userland and terminates the process if unhandled (as it is by default).
From your code the arr would point to not allocated memory so if you tried to work with it it would contain absolutely random data.
I once worked on an embedded system, and, as luck sometimes happens, I had the debugger connected near the correct place at the correct time (with respect to the delete) when the system crashed. The code was C++, the debugger was gdb, vxWorks is an embedded system tool suite.
The code I inspected was in some ways similar to your question, essentially a dereference of the pointer occurred after the delete.
...
char* ptr = new char [100];
delete [] ptr;
// more stuff that did not affect what ptr pointed to
// about 5 to 9 lines later
char retVal = ptr[x]; // <<< invalid access crash
...
The crash indicated that ptr[x] is invalid.
That embedded system (vxWorks) had techniques to confirm that where ptr pointed was indeed no longer in context, unmapped from that task.
I would guess it unusual (because of performance), but the delete not only released the block from dynamic memory, it also released the block of memory from the thread memory space, making the address invalid, causing a bus error.
I do not know how to confirm the similar information in Linux.
What happens to arr after ptr memory is deallocated?
The auto variables are unaffected by the delete.
Can I use this returned value?
Behavior is undefined (i.e. UB), so you should want to avoid doing so.
Will it cause any compile-time/Run-time error? Or any thing else.
UB means any thing else can happen.

Does delete (non array form) know the total amount of memory allocated by either new or new[]

This question was asked as part of Does delete[] deallocate memory in one shot after invoking destructors? but moved out as a separate question.
It seems (Correct me if wrong) that the only difference between delete and delete[] is that delete[] will get the array size information and invoke destructors on all of them, while delete will destruct the only first one. In particular, delete also has access to the info on how much total memory is allocated by new[].
If one doesn't care about destructing the dynamically allocated array elements, and only care that the memory allocated either by new or new[] be deallocated, delete seems to be able to do the same job.
This How does delete[] "know" the size of the operand array? question's accepted answer has one comment from #AnT and I quote
Also note that the array element counter is only needed for types with non-trivial destructor. For types with trivial destructor the counter is not stored by new[] and, of course, not retrieved by delete[]
This comment suggests that in general delete expression knows the amount of the entire memory allocated and therefore knows how much memory to deallocate in one shot in the end, even if the memory hold an array of elements. So if one writes
auto pi = new int[10];
...
delete pi;
Even though the standard deems this as UB, on most implementations, this should not leak memory (albeit it is not portable), right?
Under the C++ standard, calling delete on something allocated with new[] is simply undefined behavior, as is calling delete[] on something allocated with new.
In practice, new[] will allocate the memory through something like malloc as will new. delete will destroy the pointed-to object, then send the memory to something like free. delete[] will destroy all of the objects in the array, then send the memory to something like free. Some extra memory may be allocated by new[] to pass to delete[] to give delete[] the number of elements to be destroyed, or not.
If actual malloc/free is used, then some implementations will allow a pointer to anywhere in the malloc'd block to be used. Others won't. The exact same value is required to be passed to free as you got from malloc for this to be defined. There is an issue here in that if new[] malloced some extra room for the array size/element stride and stuck it before the block, then delete is passed the pointer-to-the-first element, then delete will pass free a different pointer than new[] got from malloc. (I think there is an architecture where something like this happens.)
Like most undefined behavior, you can no longer rely on auditing the code you write, but instead you are now committed to auditing both the produced assembly, and the C/C++ standard libraries you interact with, before you can determine if the behavior you want to do is correct. In practice, that is a burden that will not be fulfilled, so your code ends up having negative value, even if you check that things work the way you expect the one time you actually checked. How will you ensure that an identical check (of the resulting binary and its behavior) will occur every time the compiler version, standard library version, OS version, system libraries, or compiler is changed?
This is correct. Difference between delete and delete[] is that the latter knows the number of items allocated in the array and calls destructor on every object on them. To be 100% correct, both actually 'know' it - the number of items allocated for an array is equal to the allocated memory size (which both know) divided by the size of the object.
One might ask, why do we need delete[] and delete than - why can't delete perform the same calculations? The answer is polymorphism. The size of the allocated memory will not be equal to the sizeof static objec when deletion is done through the pointer to the base class.
On the other hand, delete[] does not take into account a possibility of object being polymorphed, and this is why dynamic arrays should never be treated as polymorphic objects (i.e. allocated and stored as a pointer to the base class).
As for leaking memory, delete will not leak memory in case of POD types when used on arrays.
A concrete reason to avoid all constructs provoking undefined behavior, even if you cannot see how they could possibly go wrong, is that the compiler is entitled to assume that undefined behavior never happens. For instance, given this program...
#include <iostream>
#include <cstring>
int main(int argc, char **argv)
{
if (argc > 0) {
size_t *x = new size_t[argc];
for (int i = 0; i < argc; i++)
x[i] = std::strlen(argv[i]);
std::cout << x[0] << '\n';
delete x;
}
return 0;
}
... the compiler might emit the same machine code as it would for ...
int main(void) { return 0; }
... because the undefined behavior on the argc > 0 control path means the compiler may assume that path is never taken.

Does a pointer point to the stack or heap after using delete?

In these lines of C++ code:
int * p = new int(33);
delete(p);
*p = 13;
cout << *p << endl;
The output is 13;
P points to an address on the heap initially, then I use the delete keyword to deallocate p's assigned memory address, but can still assign the memory address a value of 23; Is this the same address on the heap that p pointed to after "int * p = new int(33)" or does p point to an address on the stack after using delete(p)?
It still points to the same address (you can tell by printing the address). You'll sometimes see people assign NULL or nullptr or 0 to a pointer after freeing the memory to ensure they don't try to try to dereference the freed memory because it doesn't get assigned null for them. This allows them to have code such as this:
if (p != nullptr)
//do something with p, it hasn't been freed and set to nullptr
That's hard to do if it isn't set to null when it is freed, but do note that a smart pointer provides a safer, consistent alternative to the above.
The reason you're getting the correct output is undefined behaviour. It could crash, it could blow up, or it could work. I guess it chose to work.
Deleting p signals to whoever manages the memory (the OS) that the underlying space is now free to be re-allocated by someone else for their own use. p, however, still points to the same memory location and can be dereferenced to obtain the value of what's in that memory -- note that since that memory may now be used by someone else, the underlying bits might be different from what they were before.
Yes, it still points to the heap but that memory location is not stable. The OS could reclaim it any time so the value at that memory location is not guaranteed to be what you set it to.
Also, as far as I know, all dynamic memory allocation happens on the heap, not the stack. Stack is reserved for parameters and local variables.

int* variable or int variable

I am working in C++ and have been using pointers a lot lately. I found that there are a few ways to initialize the chunks of memory that I need to use.
void functioncall(int* i)
{
*i = *i + 1;
}
int main(){
int* a = (int*)malloc(sizeof(int));
int az = 0;
functioncall(a);
functioncall(&az);
}
Notice that the first variable int* a is declared as a pointer and then I malloc the memory for it. But, with az it is not a pointer but when calling the function I get the address of the memory.
So, my question is: is there a preferred way =, or is there any penalties one over the other?
int* a = (int*)malloc(sizeof(int));
This allocates memory on the heap. You have to deallocate it on your own, or you'll run into memory leaks. You deallocate it by calling free(a);. This option is most definitely slower (since the memory has to be requested and some other background stuff has to be done) but the memory may be available as long as you call free.
int az = 0;
This "allocates" memory on the stack, which means it gets automatically destroyed when you leave the function it is declared (unless for some really rare exceptions). You do not have to tidy up the memory. This option is faster, but you do not have control over when the object gets destroyed.
a is put onto the heap, az is on the stack. The heap you are responsible to freeing the memory. With the stack when it goes out of scope it is automatically free. So the answer is when you want the data to be placed and if you require if at the end of the scope.
PS You should use new in C++
In general you should avoid dynamic memory allocations (malloc, calloc, new) when it's reasonably easy: they are slower than stack allocations, but, more importantly, you must remember to free (free, delete) manually the memory obtained with dynamic allocation, otherwise you have memory leaks (as happens in your code).
I'm not sure what you're trying to do, but there is almost never a
reason for allocating a single int (nor an array of int, for that
matter). And there are at least two errors in your functioncall:
first, it fails to check for a null pointer (if the pointer can't be
null, pass by reference), and second, it doesn't do anything: it
increments the copy of the pointer passed as an argument, and then
dereferences the initial value and throws out the value read.
Allocating small variables directly on the stack is generally faster since you don't have to do any heap operations. There's also less chance of pointer-related screwups (e.g., double frees). Finally, you're using less space. Heap overheads aside, you're still moving a pointer and an int around.
The first line (int* a = ...) is called dynamically-allocated variable, it is usually used if you don't know before the runtime that how much variables you needed, or if you need it at all.
The second line (int az = 0) is called automatic variable, it is used more regularly.
int az = 0;
functioncall(a);
This is okay, as far as behavior is concerned.
int* a = (int*)malloc(sizeof(int));
functioncall(&az);
This invokes undefined-behaviour (UB), inside the function, when you do *i++. Because malloc only allocates the memory, it does not initialize it. That means, *i is still uninitialized, and reading an uninitialized memory invokes UB; that explains why *i++ is UB. And UB, if you know, is the most dangerous thing in C++, for it means, anything can happen.
As for the original question, what would you prefer? So the answer is, prefer automatic variable over pointer (be it allocated with malloc or new).
Automatic means Fast, Clean and Safe.
func(typename* p)
pointer is call value
*p++ is *p and p++
if change this pointer , not change original.