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.
Related
i have quick question (i think quick). I have to check if pointer is NULL after delete data pointed by pointer. In my case i have data stored in fl->first and i want to clear this data. After clear by delete fl->first i have to check if fl->first pointer is NULL. I read a lot of posts that
delete fl->first;
fl->first = NULL;
is not good idea. And is there better way or in this case it is okey?
You should not use the NULL macro in C++. Using nullptr literal is preferable instead. This is because the macro is ambiguous in some cases which may lead to confusion.
Besides that, you should typically avoid owning bare pointers, and thus deleting anything directly is usually not a good idea.
fl->first = nullptr; is C++ way of pointing to address of 0 in most cases (it does not mean that it is always 0). Why because in C you have void * in C++ you do not. You better read this.
That is as simple as it gets.
Longer answer is in void * you can allocate memory for 1000 chars, but you can read and write ints into them. To avoid this and for compilers to be more type safe C++ is going away from NULL and void *.
Yes this is a good idea, the reason being that it avoids crashes if you accidentally try to delete the same object again.
Example:
Foo* foo = new Foo(); // Create a new object
delete foo; // Deletes the object
delete foo; // Tries to delete an already deleted object and will therefor crash the program
Fix:
Foo* foo = new Foo(); // Create a new object
delete foo; // Deletes the object
foo = 0; // Sets the pointer to 0 (nullptr)
delete foo; // Deletes nothing, the program will NOT crash
Is it always wise to use NULL after a delete in legacy code without any smartpointers to prevent dangling pointers? (bad design architecture of the legacy code excluded)
int* var = new int(100);
delete var;
var = NULL;
Does it also make sense in destructors?
In a getter, does it make sense to test for NULL in second step?
Or is it undefinied behavier anyway?
Foo* getPointer() {
if (m_var!=NULL) { // <-is this wise
return m_var;
}
else {
return nullptr;
}
}
What about this formalism as an alternative? In which cases will it crash?
Foo* getPointer() {
if (m_var) { // <-
return m_var;
}
else {
return nullptr;
}
}
(Edit) Will the code crash in example 3./4. if A. NULL is used after delete or B. NULL is not used after delete.
Is it always wise to use NULL after a delete in legacy code without any smartpointers to prevent dangling pointers? (bad design architecture of the legacy code excluded)
int* var = new int(100);
// ...
delete var;
var = NULL;
Only useful if you test var afterward.
if scope ends, or if you set other value, setting to null is unneeded.
Does it also make sense in destructors?
nullify members in destructor is useless as you cannot access them without UB afterward anyway. (but that might help with debugger)
In a getter, does it make sense to test for NULL in second step? Or is it undefinied behavier anyway?
[..]
[..]
if (m_var != NULL) and if (m_var) are equivalent.
It is unneeded, as, if pointer is nullptr, you return nullptr,
if pointer is not nullptr, you return that pointer, so your getter can simply be
return m_var;
Avoid writing code like this
int* var = new int(100);
// ... do work ...
delete var;
This is prone to memory leaks if "do work" throws, returns or otherwise breaks out of current scope (it may not be the case right now but later when "do work" needs to be extended/changed). Always wrap heap-allocated objects in RAII such that the destructor always runs on scope exit, freeing the memory.
If you do have code like this, then setting var to NULL or even better a bad value like -1 in a Debug build can be helpful in catching use-after-free and double-delete errors.
In case of a destructor:
Setting the pointer to NULL in a destructor is not needed.
In production code it's a waste of CPU time (writing a value that will never be read again).
In debug code it makes catching double-deletes harder. Some compilers fill deleted objects with a marker like 0xDDDDDDDD such that a second delete or any other dereference of the pointer will cause a memory access exception. If the pointer is set to NULL, delete will silently ignore it, hiding the error.
This question is really opinion-based, so I'll offer some opinions ... but also a justification for those opinions, which will hopefully be more useful for learning than the opinions themselves.
Is it always wise to use NULL after a delete in legacy code without any smartpointers to prevent dangling pointers? (bad design architecture of the legacy code excluded)
Short answer: no.
It is generally recommended to avoid raw pointers whenever possible. Regardless of which C++ standard your code claims compliance with.
Even if you somehow find yourself needing to use a raw pointer, it is safer to ensure the pointer ceases to exist when no longer needed, rather than setting it to NULL. That can be achieved with scope (e.g. the pointer is local to a scope, and that scope ends immediately after delete pointer - which absolutely prevents subsequent use of the pointer at all). If a pointer cannot be used when no longer needed, it cannot be accidentally used - and does not need to be set to NULL. This also works for a pointer that is a member of a class, since the pointer ceases to exist when the containing object does i.e. after the destructor completes.
The idiom of "set a pointer to NULL when no longer needed, and check for NULL before using it" doesn't prevent stupid mistakes. As a rough rule, any idiom that requires a programmer to remember to do something - such as setting a pointer to NULL, or comparing a pointer to NULL - is vulnerable to programmer mistakes (forgetting to do what they are required to do).
Does it also make sense in destructors?
Generally speaking, no. Once the destructor completes, the pointer (assuming it is a member of the class) will cease to exist as well. Setting it to NULL immediately before it ceases to exist achieves nothing.
If you have a class with a destructor that, for some reason, shares the pointer with other objects (i.e. the value of the pointer remains valid, and presumably the object it points at, still exist after the destructor completes) then the answer may be different. But that is an exceedingly rare use case - and one which is usually probably better avoided, since it becomes more difficult to manage lifetime of the pointer or the object it points at - and therefore easier to introduce obscure bugs. Setting a pointer to NULL when done is generally not a solution to such bugs.
In a getter, does it make sense to test for NULL in second step? Or is it undefinied behavier anyway?
Obviously that depends on how the pointer was initialised. If the pointer is uninitialised, even comparing it with NULL gives undefined behaviour.
In general terms, I would not do it. There will presumably be some code that initialised the pointer. If that code cannot appropriately initialise a pointer, then that code should deal with the problem in a way that prevents your function being called. Examples may include throwing an exception, terminating program execution. That allows your function to safely ASSUME the pointer points at a valid object.
What about this formalism as an alternative? In which cases will it crash?
The "formalism" is identical to the previous one - practically the difference is stylistic. In both cases, if m_var is uninitialised, accessing its value gives undefined behaviour. Otherwise the behaviour of the function is well-defined.
A crash is not guaranteed in any circumstances. Undefined behaviour is not required to result in a crash.
If the caller exhibits undefined behaviour (e.g. if your function returns NULL the caller dereferences it anyway) there is nothing your function can do to prevent that.
The case you describe remains relatively simple, because the variable is described in a local scope.
But look for example at this scenario:
struct MyObject
{
public :
MyObject (int i){ m_piVal = new int(i); };
~MyObject (){
delete m_piVal;
};
public:
static int *m_piVal;
};
int* MyObject::m_piVal = NULL;
You may have a double free problem by writing this:
MyObject *pObj1 = new MyObject(1);
MyObject *pObj2 = new MyObject(2);
//...........
delete pObj1;
delete pObj2; // You will have double Free on static pointer (m_piVal)
Or here:
struct MyObject2
{
public :
MyObject2 (int i){ m_piVal = new int(i); };
~MyObject2 (){
delete m_piVal;
};
public:
int *m_piVal;
};
when you write this:
MyObject2 Obj3 (3);
MyObject2 Obj4 = Obj3;
At destruction, you will have double Free here because Obj3.m_piVal = Obj4.m_piVal
So there are some cases that need special attention (Implement : smart pointer, copy constructor, ...) to manage the pointer
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;
}
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)).
I have a class pointer declaration:
MyClass* a;
In destruction method I have:
if (a)
{
delete a;
a= NULL;
}
I got a problem when delete the pointer a:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
What is the cause of the problem and how can I get rid of it?
With your current declaration:
MyClass* a;
a gets a random value. If you never give it a valid value later, such as:
a = new MyClass();
It will point to an unknown place in memory, quite probably not a memory area reserved for your program, and hence the error when you try to delete it.
The easiest way to avoid this problem is to give a a value when you declare it:
MyClass* a = new MyClass();
or, if you cannot give it a value when you declare it (maybe you don't know it yet), assign it to null:
MyClass* a = 0;
By the way, you can remove the test (if (a)) from your code. delete is a no-op on a null pointer.
Use smart pointer to free memory. delete in application code is always wrong.
unless you have initialized the pointer to something after this:
MyClass* a;
the pointer a will hold some random value. So your test
if (a) { }
will pass, and you attempt to delete some random memory location.
You can avoid this by initializing the pointer:
MyClass* a = 0;
Other options are that the object pointed to has been deleted elsewhere and the pointer not set to 0, or that it points to an object that is allocated on the stack.
As has been pointed out elsewhere, you could avoid all this trouble by using a smart pointer as opposed to a bare pointer in the first place. I would suggest having a look at std::unique_ptr.
How did you allocate the memory that a points to? If you used new[] (in order to create an array of MyClass), you must deallocate it with delete[] a;. If you allocated it with malloc() (which is probably a bad idea when working with classes), you must deallocate it with free().
If you allocated the memory with new, you have probably made a memory management error somewhere else - for instance, you might already have deallocated a, or you have written outside the bounds of some array. Try using Valgrind to debug memory problems.
You should use
MyClass* a = NULL;
in your declaration. If you never instantiate a, the pointer is pointing to an undefined region of memory. When the containing class destructor executes, it tries to delete that random location.
When you do MyClass* a; you declare a pointer without allocating any memory. You don't initialize it, and a is not necessarily NULL. So when you try to delete it, your test if (a) succeeds, but deallocation fails.
You should do MyClass* a = NULL; or MyClass* a(nullptr); if you can use C++11.
(I assume here you don't use new anywhere in this case, since you tell us that you only declare a pointer.)