Hi all,
I am very interested in C++ code safety and believe that the smart pointers since tr1 go a long way as far as guaranteeing memory correctness. However I feel there has been a lost opportunity when it comes to the std::shared_ptr<T>::operator ->. I have attempted to create a very simple example to demonstrate this:
This program design is flawed in that we are wiping the last reference count whilst inside a method of the object being deleted. As far as C++ goes, this is not a problem. However, when we then try to access a member variable after this has happened, we will encounter a use after free scenario. In this simple example, the flawed design is easy to detect but if the class leading to the decreased reference count was hidden much further down a number of calls, I would personally find it hard to detect and instead have to rely on some memory checking tools such as Valgrind. I would have thought something more mechanical using RAII would have been good to put in place here.
For example, in a toy wrapper around std::shared_ptr<T> I demonstrate that the operator-> has been overloaded to temporarily increase the reference count during the lifetime of that call.
It does this by taking advantage of the special case of operator -> recursing down until a pointer is found. With this in place, the lifetime of the object is guaranteed whilst we are inside one of its methods.
I use something similar to this whilst debugging my own projects for both smart pointers and iterators but instead, to achieve the same API / behavior compatibility with standard C++, I make it guarantee an abort rather than protect against the use after free so I can attempt to find the broken design via the stack trace.
Is there any reason why this functionality is not included in the design of shared_ptr? Does it cause other issues I have not yet anticipated?
Interestingly std::weak_ptr is immune to this error scenario described above because of the explicit need to call lock() before you can use operator -> to access the method. This performs that necessary increase to reference count. This seems to work well so I am assuming that the same would have also been a good addition to shared_ptr?
Best regards,
Karsten