How to prevent Dangling Pointer in C++ Legacy Code - c++

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

Related

Dangling Pointers after Destructor is called

I went through this post and had a doubt. Is it a good practice to null an element of an object in its destructor?
The destructor will be called when the object goes out of scope but will its elements need to be set to NULL in the destructor to ensure dangling pointers are not left.
After an object is destroyed, it ceases to exist. There is no point in setting its members to particular values when those values will immediately cease to exist.
The pattern of setting pointers to NULL when deleteing the objects they point to is actively harmful and has caused errors in the past. Unless there's a specific reason the pointer needs to be set to NULL (for example, it is likely to be tested against NULL later) it should not be set to NULL.
Consider:
Foo* foo getFoo();
if (foo!=NULL)
{
do_stuff();
delete foo;
}
// lots more code
return (foo == NULL);
Now, imagine if someone adds foo = NULL; after the delete foo; in this code, thinking that you're supposed to do that. Now the code will give the wrong return value.
Next, consider this:
Foo* foo getFoo();
Foo* bar = null;
if (foo != NULL)
{
bar = foo;
do_stuff(bar);
delete bar;
bar = NULL;
}
// lots more code
delete foo;
We always set pointers to NULL after we delete them, so this delete foo; must be safe, right? Clearly it's not. So setting pointers to NULL after you delete them is neither necessary nor sufficient.
Don't do it.
It's not necessary to set member elements to NULL in the destructor, as delete has been called on the owner object in order for that destructor to be called. It is the responsibility of the code that deletes an object to no longer try to access the contents of that object.
You are also using extra cycles clearing out that memory.
The point of doing this is to provide deterministic behavior in event of a programming error.
If the deleted pointer is used, then the program will always fail on dereferencing a nullptr. (Not allowing the program to continue.)
If the deleted pointer set to nullptr and is then deleted again, then the second attempt is a noop (by design).
This is the normal pattern for pointers that are NOT deleted in a destructor. (Smart pointers are your friend, to avoid this situation, entirely.)
The purpose of nulling a deleted member pointer in a destructor is less obvious; when there is a suspicion that other code may have a reference to that member. This should generally be avoided (to rely on this), because it has limited utility once the memory for the destructed class is reclaimed. Although implementation dependent, in many environments the memory can live long enough to cause the program to fail when the deleted memory is re-used, so that the programmer can find the issue and fix it.

*new is always wrong. ALWAYS

So as to explain about pointers and references in this question I wrote this code.
MyClass& MyClass::MyInstance()
{
static MyClass & myLocalVariable = * new MyClass(/*parameters*/);
return myLocalVariable ;
}
one of the comments, by a really impressive high reputation SO user, simply states:
*new is always wrong. ALWAYS.
It is the first time I'm told about this: Is it a famous coding standard we all should know about ? What are the reasons behind ?
I'm normally pragmatic, however this is too much even for me!
static MyClass & myLocalVariable = * new MyClass(/*parameters*/);
Seriously? Why not simply:
static MyClass myLocalVariable{/*parameters*/};
The most obvious reason is that if you don't keep a copy of the pointer which new returned, you're not likely to ever call delete on it.
On a more human level, it will make people reading your code think less of you, and that's never a good thing either.
I believe the stated user meant that allocating a static object using new is dangerous as the memory will most probably be leaked. Even more importantly your variable is not a pointer but a reference so the chance that you never free the memory returned by new is even greater(how often do you delete the address of a reference?).
THE problem is more than just useless allocations.
If nobody calls delete on it, it won't be deleted. Sure, the memory will be released when the program ends but its destructor doesn't get called.
Compare the output of using Get() and Get2() in the code below:
#include <iostream>
struct A
{
~A(){std::cout << "Deleted\n";}
};
A& Get()
{
static A & a = *new A;
return a;
}
A& Get2()
{
static A a;
return a;
}
int main()
{
//Case 1
Get();
//Case 2
Get2();
}
The output of this program is nothing when calling Get and Deleted when calling Get2.
In other words, resources with nontrivial destructors (commit-on-close file handle for example) will not be destroyed properly at program termination in case 1, but will in case 2.
The problem is that a raw new does not specify ownership. If I new up an object and return it, who owns it? Does the creating function/object own it, or does the calling function? If you return smart pointers (std::shared_ptr and std::unique_ptr) you are specifying ownership.
Not specifying ownership is one of the easiest ways to leak memory. I have the hardest time, even with professional programmers, getting people to understand ownership and work with it. This is mostly prevented by using good types (smart pointers) that specify ownership, just by existing.
type* function(); // Unspecified ownership.
// Must be well documented and all users must read
// and follow the documentation.
std::unique_ptr<type> function(); // Calling function owns returned pointer.
// Single ownership.
std::shared_ptr<type> function(); // Calling function owns returned pointer.
// Shared ownership. Can have multiple owners.
std::weak_ptr<type> function(); // Calling function references returned pointer.
// Must lock pointer to get owned object, if not deleted.
// Shared ownership. Can have multiple owners.
These different types of pointers express ownership just by existing unlike raw pointers.
As for new always being wrong. That is an overbroad generalization. std::shared_ptr is created using the global function std::make_shared. As of C++11 there is no std::make_unique, but that will be fixed in C++14. The only way to create a std::unique_ptr is to use new and immediately assign the pointer to a std::unique_ptr.
There are also places where you would want a raw pointer and to manually use new and delete, but they tend to be very low level and most programmers will rarely encounter them.
What really has me cringing about your code is not that you are using new but that you are dereferencing the pointer and assigning it to a reference. It would be almost impossible to guarantee that the destructor will ever be called. It also tends to leak memory, though in the case of assigning to a static variable it will be deallocated at program termination so you aren't really looking at memory leaking.
MyClass& MyClass::MyInstance()
{
static MyClass & myLocalVariable = * new MyClass(/*parameters*/);
return myLocalVariable ;
}
I would prefer to create to have the static variable be by value than by reference. This prevents putting the object on the heap. Depending on MyClass is could also allow the object to be mapped to memory from the executable without having to run any code to initialize it.
MyClass& MyClass::MyInstance()
{
static MyClass myLocalVariable(/*parameters*/);
return myLocalVariable ;
}

Check for non-deallocated pointer

Assume a pointer object is being allocated on one point and it is being returned to different nested functions. At one point, I want to de-allocate this pointer after checking whether it is valid or already de-allocated by someone.
Is there any guarantee that any of these will work?
if(ptr != NULL)
delete ptr;
OR
if(ptr)
delete ptr;
This code does not work. It always gives Segmentation Fault
#include <iostream>
class A
{
public:
int x;
A(int a){ x=a;}
~A()
{
if(this || this != NULL)
delete this;
}
};
int main()
{
A *a = new A(3);
delete a;
a=NULL;
}
EDIT
Whenever we talk about pointers, people start asking, why not use Smart Pointers.
Just because smart pointers are there, everyone cannot use it.
We may be working on systems which use old style pointers. We cannot convert all of them to smart pointers, one fine day.
if(ptr != NULL) delete ptr;
OR
if(ptr) delete ptr;
The two are actually equivalent, and also the same as delete ptr;, because calling delete on a NULL pointer is guaranteed to work (as in, it does nothing).
And they are not guaranteed to work if ptr is a dangling pointer.
Meaning:
int* x = new int;
int* ptr = x;
//ptr and x point to the same location
delete x;
//x is deleted, but ptr still points to the same location
x = NULL;
//even if x is set to NULL, ptr is not changed
if (ptr) //this is true
delete ptr; //this invokes undefined behavior
In your specific code, you get the exception because you call delete this in the destructor, which in turn calls the destructor again. Since this is never NULL, you'll get a STACK OVERFLOW because the destructor will go uncontrollably recursive.
Do not call delete this in the destructor:
5.3.5, Delete: If the value of the operand of the delete-expression is not a null pointer value, the delete-expression will
invoke the destructor (if any) for the object or the elements of the array being deleted.
Therefore, you will have infinite recursion inside the destructor.
Then:
if (p)
delete p;
the check for p being not null (if (x) in C++ means if x != 0) is superfluous. delete does that check already.
This would be valid:
class Foo {
public:
Foo () : p(0) {}
~Foo() { delete p; }
private:
int *p;
// Handcrafting copy assignment for classes that store
// pointers is seriously non-trivial, so forbid copying:
Foo (Foo const&) = delete;
Foo& operator= (Foo const &) = delete;
};
Do not assume any builtin type, like int, float or pointer to something, to be initialized automatically, therefore, do not assume them to be 0 when not explicitly initializing them (only global variables will be zero-initialized):
8.5 Initializers: If no initializer is specified for an object, the object is default-initialized; if no initialization is performed, an
object with automatic or dynamic storage duration has indeterminate value. [ Note: Objects with static or thread storage duration are zero-initialized
So: Always initialize builtin types!
My question is how should I avoid double delete of a pointer and prevent crash.
Destructors are ought to be entered and left exactly once. Not zero times, not two times, once.
And if you have multiple places that can reach the pointer, but are unsure about when you are allowed to delete, i.e. if you find yourself bookkeeping, use a more trivial algorithm, more trivial rules, or smart-pointers, like std::shared_ptr or std::unique_ptr:
class Foo {
public:
Foo (std::shared_ptr<int> tehInt) : tehInt_(tehInt) {}
private:
std::shared_ptr<int> tehInt_;
};
int main() {
std::shared_ptr<int> tehInt;
Foo foo (tehInt);
}
You cannot assume that the pointer will be set to NULL after someone has deleted it. This is certainly the case with embarcadero C++ Builder XE. It may get set to NULL afterwards but do not use the fact that it is not to allow your code to delete it again.
You ask: "At one point, I want to de-allocate this pointer after checking whether it is valid or already de-allocated by someone."
There is no portable way in C/C++ to check if a >naked pointer< is valid or not. That's it. End of story right there. You can't do it. Again: only if you use a naked, or C-style pointer. There are other kinds of pointers that don't have that issue, so why don't use them instead!
Now the question becomes: why the heck do you insist that you should use naked pointers? Don't use naked pointers, use std::shared_ptr and std::weak_ptr appropriately, and you won't even need to worry about deleting anything. It'll get deleted automatically when the last pointer goes out of scope. Below is an example.
The example code shows that there are two object instances allocated on the heap: an integer, and a Holder. As test() returns, the returned std::auto_ptr<Holder> is not used by the caller main(). Thus the pointer gets destructed, thus deleting the instance of the Holder class. As the instance is destructed, it destructs the pointer to the instance of the integer -- the second of the two pointers that point at that integer. Then myInt gets destructed as well, and thus the last pointer alive to the integer is destroyed, and the memory is freed. Automagically and without worries.
class Holder {
std::auto_ptr<int> data;
public:
Holder(const std::auto_ptr<int> & d) : data(d) {}
}
std::auto_ptr<Holder> test() {
std::auto_ptr<int> myInt = new int;
std::auto_ptr<Holder> myHolder = new Holder(myInt);
return myHolder;
}
int main(int, char**) {
test(); // notice we don't do any deallocations!
}
Simply don't use naked pointers in C++, there's no good reason for it. It only lets you shoot yourself in the foot. Multiple times. With abandon ;)
The rough guidelines for smart pointers go as follows:
std::auto_ptr -- use when the scope is the sole owner of an object, and the lifetime of the object ends when the scope dies. Thus, if auto_ptr is a class member, it must make sense that the pointed-to object gets deletes when the instance of the class gets destroyed. Same goes for using it as an automatic variable in a function. In all other cases, don't use it.
std::shared_ptr -- its use implies ownership, potentially shared among multiple pointers. The pointed-to object's lifetime ends when the last pointer to it gets destroyed. Makes managing lifetime of objects quite trivial, but beware of circular references. If Class1 owns an instance of Class2, and that very same instance of Class2 owns the former instance of Class1, then the pointers themselves won't ever delete the classes.
std::weak_ptr -- its use implies non-ownership. It cannot be used directly, but has to be converted back to a shared_ptr before use. A weak_ptr will not prevent an object from being destroyed, so it doesn't present circular reference issues. It is otherwise safe in that you can't use it if it's dangling. It will assert or present you with a null pointer, causing an immediate segfault. Using dangling pointers is way worse, because they often appear to work.
That's in fact the main benefit of weak_ptr: with a naked C-style pointer, you'll never know if someone has deleted the object or not. A weak_ptr knows when the last shared_ptr went out of scope, and it will prevent you from using the object. You can even ask it whether it's still valid: the expired() method returns true if the object was deleted.
You should never use delete this. For two reasons, the destructor is in the process of deleting the memory and is giving you the opportunity to tidy up (release OS resources, do a delete any pointers in the object that the object has created). Secondly, the object may be on the stack.

Null pointers in C++

I've got a couple of questions regarding pointers. First:
ObjectType *p;
p->writeSomething();
Why is it possible to call a method on an object when the pointer hasn't been initialized? If I run that code I get the output from "writeSomething()" in my console window. Second:
ObjectType *p;
if(p==NULL)
cout<<"Null pointer";//This is printed out
p = new ObjectType;
delete p;
if(p==NULL)
cout<<"Null pointer";
else
cout<<"Pointer is not null";//This is printed out
Why isn't the pointer null in the second if statement and how do I check if a pointer isn't pointing to any memory address? I'm also wondering if there is any way to check if some memory hasn't been released when a program is done executing. For example, if you forget to write 1 delete statement in the code.
The first code is undefined behavior, anything can happen, even appearing to work. It's probably working because the call is resolved statically, and you're not accessing any members of the class.
For the second snippet delete doesn't set the pointer to NULL, it just releases the memory. The pointer is now dangling, as it points to memory you no longer own.
Your code does of course exhibit undefined behaviour, but here's an example of why it may appear possible to call a member function even if there is no object: If the member function doesn't refer to any member objects of the class, then it will never need to access any part of the memory which you haven't initialized. That means, your member function is essentially static.
As you know, member functions can be considered as normal, free functions which have an implicit instance object reference argument. For example, a simple class Foo defined like this,
struct Foo
{
void bar() { std::cout << "Hello\n"; }
};
could be implemented as a single, free function:
void __Foo_bar(Foo * this)
{
std::cout << "Hello\n";
}
Now when you say Foo * p; p->bar();, this amounts to a free function call __Foo_bar(p);. You end up passing an invalid pointer to the function, but since the function never makes use of the pointer, no harm is done.
On the other hand, if your class had a member object, like int Foo::n;, and if the member function was trying to access it, your implementation would try and access this->n, which would very likely cause an immediate problem since you'd actually be dereferencing an invalid pointer.
delete p;
deallocates memory, but it does not change the value of the address stored in p.
There is no method in standard C++ to detect that a pointer is referring to invalid memory. It is your responsibility not to de-reference an invalid pointer.
Your first example is undefined behaviour. One of the possible outcomes of undefined behaviour is that the program works the way you intended it to. Again, it is your responsibility not to write programs with undefined behaviour.
In your code, writeSomething() is probably a non-virtual member function that does not de-reference this which is why it happens to work for you, on your compiler. Most likely if you tried to refer to some member data fields then you would encounter a runtime error.
delete would call upon the destructor of ObjectType followed by de-allocation of memory but it doesn't explicitly makes your pointer NULL
That is something you have to do as a good programming practice.

Should pointers to "raw" resources be zeroed in destructors?

When I wrap "raw" resources in a C++ class, in destructor code I usually simply release the allocated resource(s), without paying attention to additional steps like zeroing out pointers, etc.
e.g.:
class File
{
public:
...
~File()
{
if (m_file != NULL)
fclose(m_file);
}
private:
FILE * m_file;
};
I wonder if this code style contains a potential bug: i.e. is it possible that a destructor is called more than once? In this case, the right thing to do in the destructor would be to clear pointers to avoid double/multiple destructions:
~File()
{
if (m_file != NULL)
{
fclose(m_file);
m_file = NULL; // avoid double destruction
}
}
A similar example could be made for heap-allocated memory: if m_ptr is a pointer to memory allocated with new[], is the following destructor code OK?
// In destructor:
delete [] m_ptr;
or should the pointer be cleared, too, to avoid double destruction?
// In destructor:
delete [] m_ptr;
m_ptr = NULL; // avoid double destruction
No. It is useful if you have a Close() function or the like:
void Close()
{
if (m_file != NULL)
{
fclose(m_file);
m_file = NULL;
}
}
~File()
{
Close();
}
This way, the Close() function is idempotent (you can call it as many times as you want), and you avoid one extra test in the destructor.
But since destructors in C++ can only be called once, assigning NULL to pointers there is pointless.
Unless, of course, for debuggin-purposes, particularly if you suspect a double-delete.
If a destructor is called more than once, you already have undefined behavior. This will also not affect clients that may have a pointer to the resource themselves, so this is not preventing a double delete. A unique_ptr or scoped_ptr seem to be better solutions to me.
In a buggy application (for example, improper use of std::unique_ptr<> can result in two std::unique_ptr<> holding the same raw pointer), you can end up with a double delete, as the second one goes out of scope.
We care about these bad cases - otherwise, what's the point of discussing setting a pointer to nullptr in the destructor? It's going away anyways!
Hence, in this example, at least, it would be better to let the program seg-fault inside a debugger during a unit-test, so you can trace the real cause of the problem.
So, in general, I don't find setting pointers to nullptr to be particularly useful for memory management.
You could do it, but a more robust alternative is to do unit tests and to judiciously use a memory checker like valgrind.
After all, with some memory errors, your program can seemingly run ok many times, until it crashes unexpectedly - much safer to do quality assurance with a memory checker, especially as your program gets larger, and memory errors become less obvious.