In a Visual C++ program, I am calling delete on a pointer. I will later need to check if the pointer has been deleted. I've noticed Visual C++ will set the address to 0x00000000, but later that value might be changed to something like 0xABABABAB, 0xFEEEFEEE, or some other value such as that. Checking for NULL only works on 0x00000000 addresses.
Is there a reliable way that I can check if the pointer was deleted, regardless of these changes the address may undergo?
If you are deleting a pointer to an object, you can see the destructor. If you want to know whether memory free operation was performed or not, there is no reliable/portable way to know this. Memory management is implementation dependant. Even this is possible that memory freeing is deferred by the library. But you should always believe that delete never fails. And if you have not overloaded delete operator, you can rely on libraries that memory would be released.
About memory contents, after contents being freed, you should not access them as the behaviour is undefined.
If you want this for debugging purpose, I would suggest using some alternate technique.
If you want to know whether pointer was freed, you should explicitly set it to 0, and you can later compare pointer with 0 to check whether it was freed.
if (...) {
delete ptr;
ptr = 0; // set explicitly
}
...
if(0 == ptr) {
// Pointer was freed
...
} else {
// Pointer was not freed
...
}
If you use C++11 you can just set the value of the pointer to nullptr and test for that afterwards (like if (foo == nullptr)).
Related
I have a member function that I call, from there I get a pointer to a private member which is of class BankAccount, I am unsure what happens with the pointers when I deallocate them. I create a new pointer and heap memory address but then assign the pointer to something else. What does "delete" end up deleting?
I read that if you delete a pointer
Here is the code
void Employee::raise(){
BankAccount* tempBank = new BankAccount(); //set pointer to new heap place
double amt;
tempBank = get_bank(); // set pointer to existing heap implicitly
amt = tempBank->get_amount();
amt = (amt + (amt/12));
tempBank->set_amount(amt);
delete tempBank; //does this delete new heap created or does it add a new block of
//memory to heap since it is trying to delete a pointer assigned
//by memory address
tempBank = NULL;
}
I realized I could just do the code below to avoid this situation, but now I am curious as to what happens in the above situation with the memory
BankAccount* tempBank = get_bank();
So what exactly happens when delete is called in my original situation?
When you use delete ptr; the object pointed to by ptr is destroyed and the corresponding memory is returned to the memory management system. The variable ptr and any copy thereof hold a bit pattern referring to now inaccessible memory (the system may still allow you to actually access this memory and it may even still contain the original data but that's undefined behavior and you shall not rely on it).
Put differently, the memory deallocation does not affect the pointer but it does affected the pointed to entity. In your case, the BankAccount, i.e., the result of *tempBank gets destroyed while the pointer tempBank remains unchanged by the delete operation. Obviously, setting tempBank to NULL does change this specific pointer but none of the other copies (if any), giving you false sense of security: I'd not set deleted pointers to NULL unless I keep them around for whatever reason...
Pointers are essentially just the address of the first byte in memory that belongs to the data structure they point to. So in your case:
BankAccount* tempBank = new BankAccount(); // this creates a new object of type BankAccount
// the pointer tempBank points to the first byte of that object in memory
tempBank = get_bank(); // now tempBank points to the first byte of whatever is returned from get_bank()
// that means that you no longer know the address of the object you created above (tempBank now points to something different)
// C++ has no garbage collection, so you just leaked that memory
delete tempBank; // you delete the object that was returned from get_bank
// so that memory is now marked as free and can be reused by whatever needs it
tempBank = NULL; // this is good style, you should always do it, but it does nothing to any allocated memory
BTW: using plain new and delete and owning raw pointers is considered bad style in modern C++. YOu might want to consider using std::shared_ptr or std::unique_ptr (or their boost equivalents if you cannot use C++11 yet)
I found this information that may be useful to you:
ordinary delete 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.
You can find more information in the original url: http://www.cplusplus.com/reference/new/operator%20delete/
delete tempBank;
when delete is called on pointer , it releases memory pointed by that variable[tempBank].
There are two notions of delete in C++: One is the operator, declared as ::operator delete(void*), which basically only frees up the memory and isn't usually thought about by most programmers. The other is the delete expression, delete p;, where p is a T*. The expression invokes the destructor of the object pointed to by p (and then frees the memory), which is a crucial language feature of C++ that has no analogue in C.
Well first of all, you are allocating from heap with your first exp which is
BankAccount* tempBank = new BankAccount();
and you lose the address of it with assigning another object address to tempBank pointer by
tempBank = get_bank();
so actually when you delete tempBank; you actually deleting the object that you allocated in the function get_bank(). Also because you have lost the address of object that you allocated with new BankAccount(), there is no more way to delete it, because you do not know the address of this object.
In your question, Are you sure that get_bank() indeed returns pointer to object allocated on heap (and not address of just plain object on stack). You have not mentioned it clearly hence it's worth to confirm it again. Now, coming back to question, if get_bank() returned pointer to private member which let's say was not on heap - in that case doing doing tempBank will result in undefined behavior because you can only invoke delete on an object which was created using new. But if get_bank() returned pointer to object allocated on heap then it will free memory of that object and then accessing that object from any other member function could become a nightmare!
You can check below link for some more related information,
Calling delete on variable allocated on the stack
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;
}
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.
I know that memory alloced using new, gets its space in heap, and so we need to delete it before program ends, to avoid memory leak.
Let's look at this program...
Case 1:
char *MyData = new char[20];
_tcscpy(MyData,"Value");
.
.
.
delete[] MyData; MyData = NULL;
Case 2:
char *MyData = new char[20];
MyData = "Value";
.
.
.
delete[] MyData; MyData = NULL;
In case 2, instead of allocating value to the heap memory, it is pointing to a string literal.
Now when we do a delete it would crash, AS EXPECTED, since it is not trying to delete a heap memory.
Is there a way to know where the pointer is pointing to heap or stack?
By this the programmer
Will not try to delete any stack memory
He can investigate why does this ponter, that was pointing to a heap memory initially, is made to refer local literals? What happened to the heap memory in the middle? Is it being made to point by another pointer and delete elsewhere and all that?
Is there a way to know where the pointer is pointing to heap or stack?
You can know this only if you remember it at the point of allocation. What you do in this case is to store your pointers in smart pointer classes and store this in the class code.
If you use boost::shared_ptr as an example you can do this:
template<typename T> void no_delete(T* ptr) { /* do nothing here */ }
class YourDataType; // defined elsewhere
boost::shared_ptr<YourDataType> heap_ptr(new YourDataType()); // delete at scope end
YourDataType stackData;
boost::shared_ptr<YourDataType> stack_ptr(&stackData, &no_delete); // never deleted
As soon as you need that knowledge you have already lost. Why? Because then even if you omit the wrong delete[], you still have a memory leak.
The one who creates the memory should always be the one who deletes it. If at some occasion a pointer might get lost (or overwritten) then you have to keep a copy of it for the proper delete.
There is no way in Standard C++ of determining whether a pointer points to dynamically allocated memory or not. And note that string literals are not allocated on the stack.
As most of the users said here there's no standard way to discover which memory you're dealing with.
Also, as many users pointed out, it;s a kinda perverted situation where you pass a pointer to a function which should delete it automatically if it's allocated on heap.
But if you insist, nevertheless there are some ways to discover which memory belongs to which type.
You actually deal with 3 types of memory
Stack
Heap
Global
For instance:
char* p = new char[10]; // p is a pointer, points to heap-allocated memory
char* p = "Hello, world!"; // p is a pointer, points to the global memory
char p[] = "Hello, world!"; // p is a buffer allocated on the stack and initialized with the string
Now let's distinguish them. I'll describe this in terms of Windows API and x86 assembler (since this is what I know :))
Let's start from stack memory.
bool IsStackPtr(PVOID pPtr)
{
// Get the stack pointer
PBYTE pEsp;
_asm {
mov pEsp, esp
};
// Query the accessible stack region
MEMORY_BASIC_INFORMATION mbi;
VERIFY(VirtualQuery(pEsp, &mbi, sizeof(mbi)));
// the accessible stack memory starts at mbi.BaseAddress and lasts for mbi.RegionSize
return (pPtr >= mbi.BaseAddress) && (pPtr < PBYTE(mbi.BaseAddress) + mbi.RegionSize);
}
If the pointer is allocated on the stack of another thread you should get its stack pointer by GetThreadContext instead of just taking the EIP register value.
Global memory
bool IsGlobalPtr(PVOID pPtr)
{
MEMORY_BASIC_INFORMATION mbi;
VERIFY(VirtualQuery(pPtr, &mbi, sizeof(mbi)));
// Global memory allocated (mapped) at once for the whole executable
return mbi.AllocationBase == GetModuleHandle(NULL);
}
If you're writing a DLL you should put its module handle (which is actually its base mapping pointer) instead of GetModuleHandle(NULL).
Heap
Theoretically you may assume that if the memory is neither global nor stack - it's allocated on heap.
But there's is actually a big ambiguity here.
You should know that there're different implementations of the heap (such as raw Windows heap accessed by HeapAlloc/HeapFree, or CRT-wrapped malloc/free or new/delete).
You may delete such a block via delete operator only if you know for sure it was either stack/global pointer or it was allocated via new.
In conclusion:
It's a kinda pervert trick. Should not be used generally. Better to provide some extra information with the pointer which tells how to release it.
You can only use it if you know for sure on which heap the memory was allocated (in case it's a heap memory).
I think there is no (easy) way how to tell where the memory is allocated (you might be able to determine it using a debugger, perhaps, but that is obviously not what you want). The bottom line is: never do the thing you did in case 2.
In case 2, MyData = "Value" causes a memory leak since there is no longer a reference to the memory returned from new.
There is no easy way or standard way for doing this. You can intercept the heap allocation function(s) and put each memory allocated zone in a list. Your "IsHeap" function should check if the zone passed to the function is the one from the list. This is just a hint - it is almost impossible to do this in a cross-platform manner.
But then again - why would you need that?
I often see legacy code checking for NULL before deleting a pointer, similar to,
if (NULL != pSomeObject)
{
delete pSomeObject;
pSomeObject = NULL;
}
Is there any reason to checking for a NULL pointer before deleting it? What is the reason for setting the pointer to NULL afterwards?
It's perfectly "safe" to delete a null pointer; it effectively amounts to a no-op.
The reason you might want to check for null before you delete is that trying to delete a null pointer could indicate a bug in your program.
Edit
NOTE: if you overload the delete operator, it may no longer be "safe" to delete NULL
The C++ standard guarantees that it is legal to use a null pointer in a delete-expression (§8.5.2.5/2). However, it is unspecified whether this will call a deallocation function (operator delete or operator delete[]; §8.5.2.5/7, note).
If a default deallocation function (i.e. provided by the standard library) is called with a null pointer, then the call has no effect (§6.6.4.4.2/3).
But it is unspecified what happens if the deallocation function is not provided by the standard library — i.e. what happens when we overload operator delete (or operator delete[]).
A competent programmer would handle null pointers accordingly inside the deallocation function, rather than before the call, as shown in OP’s code.Likewise, setting the pointer to nullptr/NULL after the deletion only serves very limited purpose. Some people like to do this in the spirit of defensive programming: it will make program behaviour slightly more predictable in the case of a bug: accessing the pointer after deletion will result in a null pointer access rather than a access to a random memory location. Although both operations are undefined behaviour, the behaviour of a null pointer access is a lot more predictable in practice (it most often results in a direct crash rather than memory corruption). Since memory corruptions are especially hard to debug, resetting deleted pointers aids debugging.
— Of course this is treating the symptom rather than the cause (i.e. the bug). You should treat resetting pointers as code smell. Clean, modern C++ code will make memory ownership clear and statically checked (by using smart pointers or equivalent mechanisms), and thus provably avoid this situation.
Bonus: An explanation of overloaded operator delete:
operator delete is (despite its name) a function that may be overloaded like any other function. This function gets called internally for every call of operator delete with matching arguments. The same is true for operator new.
Overloading operator new (and then also operator delete) makes sense in some situations when you want to control precisely how memory is allocated. Doing this isn't even very hard, but a few precautions must be made to ensure correct behaviour. Scott Meyers describes this in great detail Effective C++.
For now, let's just say that we want to overload the global version of operator new for debugging. Before we do this, one short notice about what happens in the following code:
klass* pobj = new klass;
// … use pobj.
delete pobj;
What actually happens here? Well the above can be roughly translated to the following code:
// 1st step: allocate memory
klass* pobj = static_cast<klass*>(operator new(sizeof(klass)));
// 2nd step: construct object in that memory, using placement new:
new (pobj) klass();
// … use pobj.
// 3rd step: call destructor on pobj:
pobj->~klass();
// 4th step: free memory
operator delete(pobj);
Notice step 2 where we call new with a slightly odd syntax. This is a call to so-called placement new which takes an address and constructs an object at that address. This operator can be overloaded as well. In this case, it just serves to call the constructor of the class klass.
Now, without further ado here's the code for an overloaded version of the operators:
void* operator new(size_t size) {
// See Effective C++, Item 8 for an explanation.
if (size == 0)
size = 1;
cerr << "Allocating " << size << " bytes of memory:";
while (true) {
void* ret = custom_malloc(size);
if (ret != 0) {
cerr << " # " << ret << endl;
return ret;
}
// Retrieve and call new handler, if available.
new_handler handler = set_new_handler(0);
set_new_handler(handler);
if (handler == 0)
throw bad_alloc();
else
(*handler)();
}
}
void operator delete(void* p) {
cerr << "Freeing pointer # " << p << "." << endl;
custom_free(p);
}
This code just uses a custom implementation of malloc/free internally, as do most implementations. It also creates a debugging output. Consider the following code:
int main() {
int* pi = new int(42);
cout << *pi << endl;
delete pi;
}
It yielded the following output:
Allocating 4 bytes of memory: # 0x100160
42
Freeing pointer # 0x100160.
Now, this code does something fundamentally different than the standard implementation of operator delete: It didn't test for null pointers! The compiler doesn't check this so the above code compiles but it may give nasty errors at run-time when you try to delete null pointers.
However, as I said before, this behaviour is actually unexpected and a library writer should take care to check for null pointers in the operator delete. This version is much improved:
void operator delete(void* p) {
if (p == 0) return;
cerr << "Freeing pointer # " << p << "." << endl;
free(p);
}
In conclusion, although a sloppy implementation of operator delete may require explicit null checks in the client code, this is non-standard behaviour and should only be tolerated in legacy support (if at all).
Deleting null is a no-op. There's no reason to check for null before calling delete.
You might want to check for null for other reasons if the pointer being null carries some additional information you care about.
Delete checks for NULL internally. Your test is redundent
According to C++03 5.3.5/2, it's safe to delete a null pointer.
This following is quoted from the standard:
In either alternative, if the value of the operand of delete is the
null pointer the operation has no effect.
If pSomeObject is NULL, delete won't do anything. So no, you don't have to check for NULL.
We consider it good practice to assign NULL to the pointer after deleting it if it's at all possible that some knucklehead can attempt to use the pointer. Using a NULL pointer is slightly better than using a pointer to who knows what (the NULL pointer will cause a crash, the pointer to deleted memory may not)
There is no reason to check for NULL prior to delete.
Assigning NULL after delete might be necessary if somewhere in the code checks are made whether some object is already allocated by performing a NULL check. An example would be some sort of cached data that is allocated on demand. Whenever you clear out the cache-object you assign NULL to the pointer so the code that allocates the object knows that it needs to perform an allocation.
I believe the previous developer coded it "redundantly" to save some milliseconds:
It's a good thing to have the pointer be set to NULL upon being deleted, so you could use a line like the following right after deleting the object:
if(pSomeObject1!=NULL) pSomeObject1=NULL;
But then delete is doing that exact comparison anyway (doing nothing if it's NULL). Why do this twice? You can always assign pSomeObject to NULL after calling delete, regardless of its current value - but this would be slightly redundant if it had that value already.
So my bet is the author of those lines tried to ensure pSomeObject1 would always be NULL after being deleted, without incurring the cost of a potentially unnecessary test and assignation.
It depends on what you are doing. Some older implementations of free, for example, will not be happy if they are passed a NULL pointer. Some libraries still have this problem. For example, XFree in the Xlib library says:
DESCRIPTION
The XFree function is a
general-purpose Xlib routine that
frees the specified data. You must
use it to free any objects that were
allocated by Xlib, unless an alternate
function is explicitly specified for
the object. A NULL pointer cannot be
passed to this function.
So consider freeing NULL pointers as a bug and you'll be safe.
As for my observations, deleting a null pointer using delete is safe in unix based machines ike PARISC and itanium. But is quite unsafe for Linux systems as the process would crash then.