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.
Related
I'm trying to understand how delete clears the memory allocated for an object.
Can anybody please explain it clearly?
I'm doing something like this:
class MyClass{
public :
MyClass() {std::cout <<" constructed\n";}
~MyClass() {std::cout <<" destroyed\n";}
};
int main ()
{
MyClass * pt=NULL;
pt = new MyClass();
delete pt;
if ( pt == NULL )
std::cout<<"deallocated\n";
}
delete pt will call the destructor ~MyClass(), then release any memory occupied by the object *pt back to the operating system.
What it doesn't do is change the value of the pointer, as that's unnecessary.
Some programmers will set pt = nullptr after a delete since the C++ standard guarantees that delete nullptr is a no-op. So it can help program stability.
delete p does indeed deallocate the storage occupied by the object pointed to by the value of p, among other things.
It does not modify the value of p, though. That wouldn't make sense. consider this:
int * funky_ptr();
delete funky_ptr();
Here the operand of delete is a prvalue; what sense would there be in modifying it?
It depends.
On debug builds, some compilers will usually clear out the memory (either set everything to 0 or some bit pattern that can be used to identity clears later) in order to help debugging.
That way, accessing a deleted object will more likely yield an access violation early on, rather than it failing silently.
On release builds, other than the (pseudo-)destructor being called, nothing else happens.
Note that setting pointers to NULL after delete or free is a code smell, as it can mask some bugs.
I'm trying to understand how delete clears the memory allocated for an object. can anybody please make it clear?
delete delete does the following:
look at the received address, and interpret it as a pointer (to data specified by the pointer type)
call the destructor(s) for all instances of data, for objects at the received address
tell the internal memory allocation subsystem, that the address in the received pointer, is now free. This will either release the memory to the operating system (so other applications can use it) or (more likely) cache it internally and use it for subsequent allocations (the next allocation performed using new or new[] with same or smaller size may receive this pointer).
These are the minimal steps to deallocate heap data in C++.
You will notice that nowhere in that list is a "set pointer to null/zero/speciffic value". This is because there are cases when the value of the pointer, is not interesting after the delete statement (such as, within a destructor body), and setting it to zero would just waste processor cycles.
As a rule of thumb, in C++ code is written so you do not pay for what you do not use. If you have use for such functionality, it is trivial to write it yourself (this example won't work for arrays):
template<typename T>
void safe_delete(T*& ptr) // use instead of delete
{
delete ptr;
ptr = nullptr;
}
I have this piece of code
int main()
{
int *b = new int(8);
cout<<" &b = "<<b<<endl;
delete b;
void *place = (void*)0x3c0fa8; //in my output i am getting this value in &b
int *i = new(place) int(8);
system("PAUSE");
return 0;
}
My doubt is that i have allocate space for "b", and deleted it, now if i allocate another integer space, it comes out to be the same location as allocated previously, now if i forcefully put integer value to this value(after delete), i am getting SEGFAULT.
What's wrong in this code?
Thanks.
It is not guaranteed that each time b will be allocated at same memory location, in fact it is extremely uncommon and you should not rely on this.
And for this case, place actually points to an invalid address, and accessing it causes Segfault.
Even if place points to same location where b were allocated, after deleting b, the memory is de-allocated and does not belong to your program. Before int *i = new(place) int(8); gets executed, that memory location may have been allocated by any other process. Hence again accessing it will cause Segfault.
Using memory that was allocated from the heap, after it has been freed (with delete) is undefined behaviour. For all we know, that cell of the heap may have been completely freed back to the OS [and thus no longer available as memory in your process] (in fact, Windows pretty much calls into the OS directly for all heap allocations, and it is possible that it frees the entire lump of memory that the heap is in).
However, it's more likely that the second new call works out, and you are simply overwriting some piece of heap memory that belongs to the heap, so when the code tries to exit (and free some stuff allocated before main), it falls over.
If you were to do it
int main()
{
int *b = new int(8);
cout<<" &b = "<<b<<endl;
// delete b;
int *i = new(b) int(8);
}
it has a good chance of working, since you are no longer using heap memory AFTER it has been freed. (Of course, you may want to change the second 8 to a 9 or something to see the difference... ;)
It looks like you are using the placement new wrong. The placement new operator is used for constructing stuff in a pre-defined location. It's meant to be used like this (This question might be useful too):
char *buffer = new char[sizeof(string)];
string *str = new (buffer) string("hello, world");//<-- this is your placement new
As you can see, the memory in which you are constructing, should be acquired by you in advance. In your example, however, you are not doing it, and trying to write into memory that you have not acquired before, which leads to segfault.
Also, as the other answer mentioned, you are by no means guaranteed to be getting the same address for b each time. Moreover, even if you get lucky, and place points to the same address as b, you still are trying to write into the memory that doesn't belong to you, since you do a delete b beforehand.
This question already has answers here:
C++ delete - It deletes my objects but I can still access the data?
(13 answers)
Closed 9 years ago.
I'm facing an issue. I wrote the following programme:
void main()
{
int *ptr;
ptr=new int;
cout<<ptr<<endl;
cout<<&ptr<<endl;
delete ptr;
// ptr= NULL;
cout<<ptr<<endl;
cout<<&ptr<<endl;
}
The output of the programme is:
0x00431810
0x0018FF44
0x00431810
0x0018FF44
"&ptr" would definitely be the same because it is ptr's own address. But 1st and third line of output clearly shows that "ptr" is pointing to the same memory location even after the "delete" is called. Why? If this is the case why do we have "delete" and not just rely on NULLING the pointer. I know that more than one pointers can point to a memory location but yeah "delete" is useless. No ? That's so confusing. please help. I've an exam tomorrow.
delete ptr does not change the value of the pointer, but it does free the memory.
Note that dereferencing ptr after freeing the memory would trigger undefined behaviour.
When you call new, you are asking the computer to allocate some memory on the heap and returns a pointer to where that is on the heap.
Calling delete does the opposite in that it tells the computer to free the memory the pointer is pointing to from the heap. This means that it can be reused by your program at a later stage.
However, it does not change the value of the pointer. It is good practise to set the pointers value to NULL. This is because, where the pointer is now pointing to could contain anything (the computer is free to reuse this memory for something else). Were you to use this pointer, it is undefined what will happen.
If you just change the pointer to NULL, then all that does it forget where you allocated the memory. Because C++ is not a managed language, it won't detect you don't have any pointer to that memory, so the memory will become lost as you can't access it (you don't know where it is) but the computer can't reuse it (it doesn't know you are done with it).
If you use a managed language like C# or Java, when there are no pointers to something on the heap, the computer frees it (known as Garbage Collection) but this comes with performance overheads so C++ leaves it up to the programmer.
pointer doesn't know if the memory is valid or corrupted. You can make pointer to point at any address that you can address (that will fit into pointer). For example on my machine pointer has 8 bytes size so I can do
int main(int argc, char** argv) {
int *ptr;
ptr=new int;
cout<<ptr<<endl;
cout<<&ptr<<endl;
delete ptr;
//ptr= NULL;
cout<<ptr<<endl;
cout<<&ptr<<endl;
ptr = (int*) 0xffffffff;
cout<<ptr<<endl; //prints 0xffffffff
ptr = (int*) 0xffffffffffffffff;
cout<<ptr<<endl; //prints 0xffffffffffffffff
ptr = (int*) 0xffffffffffffffff1;
cout<<ptr<<endl; //prints 0xfffffffffffffff1 truncated
ptr = (int*) 0xffffffffffffffff321;
cout<<ptr<<endl; //prints 0xfffffffffffff321 truncated
return 0;
}
When you are using new it will allocate memory at some address on the heap and return you a pointer to this address.
void* operator new (std::size_t size) throw (std::bad_alloc);
Pointer and memory are two distinguished things. In particular you can even specify an address which you want to use for allocation by hand(using placement new syntax):
int* ptr = new (0xff1256) int;
//correct if the memory at 0xff1256 is preallocated
//because placement new only creates object at address
//doesn't allocate memory
"ptr" is pointing to the same memory location even after the "delete"
is called. Why?
In the same way delete ptr only deallocates memory, leaving the pointer intact (this is a good practice though to assign NULL to a pointer immediately after call to delete). It only deallocate the memory, it is not interested in your pointer but in the address where to free memory. Allocating memory or deallocating it is done by operating system (i.e.the memory is being marked as allocated).
From the documentation,
Deallocates the memory block pointed by ptr (if not null), releasing
the storage space previously allocated to it by a call to operator new
and rendering that pointer location invalid.
That means, delete marks the location to be reused by any other process for any other purpose. It never says that, it will initialize the memory block to any random value, so that the earlier stored data can never be accessed again. So, there is always the possibility of having your data even after the call to delete. But, again, it is just one of the possibility of Undefined Behavior. Thats' why coders, make the pointer NULL after deallocating it.
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.
On Learn C++, they wrote this to free memory:
int *pnValue = new int; // dynamically allocate an integer
*pnValue = 7; // assign 7 to this integer
delete pnValue;
pnValue = 0;
My question is: "Is the last statement needed to free the memory correctly, completly?"
I thought that the pointer *pnValue was still on the stack and new doesn't make any sense to the pointer. And if it is on the stack it will be cleaned up when the application leaves the scope (where the pointer is declared in), isn't it?
It's not necessary, but it's always a good idea to set pointers to NULL (0) when you're done with them. That way if you pass it to a function (which would be a bug), it will likely give you an error rather than trying to operate on invalid memory (makes the bug much easier to track down). And it also makes conditionals simpler.
Setting a pointer to NULL (or zero) after deleting it is not necessary. However it is good practice. For one thing, you won't be able to access some random data if you later dereference the pointer. Additionally, you'll often find code with the following:
if(ptr)
{
delete ptr;
ptr = NULL;
}
So setting the pointer to NULL will ensure it won't be deleted twice.
Finally, you might find code like this:
void foo(bar *ptr)
{
if(!ptr) throw Exception(); // or return, or do some other error checking
// ...
}
And you'd probably want that safety check to be hit.