Consider my code below. My understanding of unique pointers was that only one unique pointer can be used to reference one variable or object. In my code I have more than one unique_ptr accessing the same variable.
It's obviously not the correct way to use smart pointers i know, in that the pointer should have complete ownership from creation. But still, why is this valid and not having a compilation error? Thanks.
#include <iostream>
#include <memory>
using namespace std;
int main()
{
int val = 0;
int* valPtr = &val;
unique_ptr <int> uniquePtr1(valPtr);
unique_ptr <int> uniquePtr2(valPtr);
*uniquePtr1 = 10;
*uniquePtr2 = 20;
return 0;
}
But still, why is this valid
It is not valid! It's undefined behaviour, because the destructor of std::unique_ptr will free an object with automatic storage duration.
Practically, your program tries to destroy the int object three times. First through uniquePtr2, then through uniquePtr1, and then through val itself.
and not having a compilation error?
Because such errors are not generally detectable at compile time:
unique_ptr <int> uniquePtr1(valPtr);
unique_ptr <int> uniquePtr2(function_with_runtime_input());
In this example, function_with_runtime_input() may perform a lot of complicated runtime operations which eventually return a pointer to the same object valPtr points to.
If you use std::unique_ptr correctly, then you will almost always use std::make_unique, which prevents such errors.
Just an addition to Christian Hackl's excellent answer:
std::unique_ptr was introduced to ensure RAII for pointers; this means, in opposite to raw pointers you don't have to take care about destruction yourself anymore. The whole management of the raw pointer is done by the smart pointer. Leaks caused by a forgotten delete can not happen anymore.
If a std::unique_ptr would only allow to be created by std::make_unique, it would be absolutely safe regarding allocation and deallocation, and of course that would be also detectable during compile time.
But that's not the case: std::unique_ptr is also constructible with a raw pointer. The reason is, that being able to be constructed with a hard pointer makes a std::unique_ptr much more useful. If this would not be possible, e.g. the pointer returned by Christian Hackl's function_with_runtime_input() would not be possible to integrate into a modern RAII environment, you would have to take care of destruction yourself.
Of course the downside with this is that errors like yours can happen: To forget destruction is not possible with std::unique_ptr, but erroneous multiple destructions are always possible (and impossible to track by the compiler, as C.H. already said), if you created it with a raw pointer constructor argument. Always be aware that std::unique_ptr logically takes "ownership" of the raw pointer - what means, that no one else may delete the pointer except the one std::unique_ptr itself.
As rules of thumb it can be said:
Always create a std::unique_ptr with std::make_unique if possible.
If it needs to be constructed with a raw pointer, never touch the raw pointer after creating the std::unique_ptr with it.
Always be aware, that the std::unique_ptr takes ownership of the supplied raw pointer
Only supply raw pointers to the heap. NEVER use raw pointers which point to local
stack variables (because they will be unavoidably destroyed automatically,
like valin your example).
Create a std::unique_ptr only with raw pointers, which were created by new, if possible.
If the std::unique_ptr needs to be constructed with a raw pointer, which was created by something else than new, add a custom deleter to the std::unique_ptr, which matches the hard pointer creator. An example are image pointers in the (C based) FreeImage library, which always have to be destroyed by FreeImage_Unload()
Some examples to these rules:
// Safe
std::unique_ptr<int> p = std::make_unique<int>();
// Safe, but not advisable. No accessible raw pointer exists, but should use make_unique.
std::unique_ptr<int> p(new int());
// Handle with care. No accessible raw pointer exists, but it has to be sure
// that function_with_runtime_input() allocates the raw pointer with 'new'
std::unique_ptr<int> p( function_with_runtime_input() );
// Safe. No accessible raw pointer exists,
// the raw pointer is created by a library, and has a custom
// deleter to match the library's requirements
struct FreeImageDeleter {
void operator() (FIBITMAP* _moribund) { FreeImage_Unload(_moribund); }
};
std::unique_ptr<FIBITMAP,FreeImageDeleter> p( FreeImage_Load(...) );
// Dangerous. Your class method gets a raw pointer
// as a parameter. It can not control what happens
// with this raw pointer after the call to MyClass::setMySomething()
// - if the caller deletes it, your'e lost.
void MyClass::setMySomething( MySomething* something ) {
// m_mySomethingP is a member std::unique_ptr<Something>
m_mySomethingP = std::move( std::unique_ptr<Something>( something ));
}
// Dangerous. A raw pointer variable exists, which might be erroneously
// deleted multiple times or assigned to a std::unique_ptr multiple times.
// Don't touch iPtr after these lines!
int* iPtr = new int();
std::unique_ptr<int> p(iPtr);
// Wrong (Undefined behaviour) and a direct consequence of the dangerous declaration above.
// A raw pointer is assigned to a std::unique_ptr<int> twice, which means
// that it will be attempted to delete it twice.
// This couldn't have happened if iPtr wouldn't have existed in the first
// place, like shown in the 'safe' examples.
int* iPtr = new int();
std::unique_ptr<int> p(iPtr);
std::unique_ptr<int> p2(iPtr);
// Wrong. (Undefined behaviour)
// An unique pointer gets assigned a raw pointer to a stack variable.
// Erroneous double destruction is the consequence
int val;
int* valPtr = &val;
std::unique_ptr<int> p(valPtr);
This example of code is a bit artificial. unique_ptr is not usually initialized this way in real world code. Use std::make_unique or initialize unique_ptr without storing raw pointer in a variable:
unique_ptr <int> uniquePtr2(new int);
Related
I have unique_ptr and a row pointer that the unique_ptr points to. How do I call release for unique_ptr using only row pointer rowPtr?
#include <iostream>
#include <memory>
int main()
{
std::unique_ptr<int> uniqPtr = std::make_unique<int>(2);
int* rowPtr = uniqPtr .get();
// call .release for uniqPtr using only rowPtr
return 0;
}
UPD:
I will clarify the question. I need uniqPtr to become empty using only rowPtr.
How do I call release for unique_ptr using only row pointer rowPtr?
You cannot. You can only release a unique pointer by calling the release member function on the unique pointer. You cannot use, nor do you need, the bare pointer to do that.
You don't. Raw pointers do not participate in ownership. Nor shall they.
When you call get you are explicitly saying: "I want only a raw pointer. I do not want to interfere with ownership of the managed pointer".
You can either use int *p = uniqPtr.release() to get the pointer without destroying it. p points still to a valid memory, but uniqPtr is no longer managing it.
You can also use uniqPtr.reset(nullptr) which would destroy the object and resets the unique_ptr to a nullptr. In this case ptr is no longer pointing to the object and the memory of that object has been freed.
In any case you can not use the raw pointer, managed by uniqPtr, to change the state of the unique_ptr object, because the raw pointer doesn't have any association with it, it's just managed by it.
A note: this is an API design question, riding on the design of the constructors of unique_ptr and share_ptr for the sake of the question, but not aiming to propose any change to their current specifications.
Though it would usually be advisable to use make_unique and make_shared, both unique_ptr and shared_ptr can be constructed from a raw pointer.
Both get the pointer by value and copy it. Both allow (i.e. in the sense of: do not prevent) a continuance usage of the original pointer passed to them in the constructor.
The following code compiles and results with double free:
int* ptr = new int(9);
std::unique_ptr<int> p { ptr };
// we forgot that ptr is already being managed
delete ptr;
Both unique_ptr and shared_ptr could prevent the above if their relevant constructors would expect to get the raw pointer as an rvalue, e.g. for unique_ptr:
template<typename T>
class unique_ptr {
T* ptr;
public:
unique_ptr(T*&& p) : ptr{p} {
p = nullptr; // invalidate the original pointer passed
}
// ...
Thus, the original code would not compile as an lvalue cannot bind to an rvalue, but using std::move the code compiles, while being more verbose and more secured:
int* ptr = new int(9);
std::unique_ptr<int> p { std::move(ptr) };
if (!ptr) {
// we are here, since ptr was invalidated
}
It is clear that there can be dozens of other bugs a user can do with smart pointers. The commonly used argument of you should know how to properly use the tools provided by the language, and C++ is not designed to watch over you etc.
But still, it seems that there could have been an option for preventing this simple bug and to encourage usage of make_shared and make_unique. And even before make_unique was added in C++14, there is still always the option of direct allocation without a pointer variable, as:
auto ptr = std::unique_ptr<int>(new int(7));
It seems that requesting rvalue reference to a pointer as the constructor parameter could add a bit of an extra safety. Moreover, the semantics of getting rvalue seems to be more accurate as we take ownership of the pointer that is passed.
Coming to the question of why didn't the standard take this more secured approach?
A possible reason might be that the approach suggested above would prevent creating a unique_ptr from const pointers, i.e. the following code would fail to compile with the proposed approach:
int* const ptr = new int(9);
auto p = std::unique_ptr { std::move(ptr) }; // cannot bind `const rvalue` to `rvalue`
But this seems to be a rare scenario worth neglecting, I believe.
Alternatively, in case the need to support initialization from a const pointer is a strong argument against the proposed approach, then a smaller step could still be achieved with:
unique_ptr(T* const&& p) : ptr{p} {
// ...without invalidating p, but still better semantics?
}
As long as they both have a get() method, invalidating the original pointer is not a "more secured", but a more confusing approach.
In the way raw pointers are used in C++, they don't represent any ownership concept by themselves and don't define the object lifetime. Anyone who uses raw pointers in C++ needs to be aware that they are only valid while the object exists (whether the object lifetime is enforced by smart pointers or by the logic of the program). Creating a smart pointer from a raw pointer does not "transfer" ownership of the object, but "assigns" it.
This distinction could be made clear in the following example:
std::unique_ptr<int> ptr1 = std::make_unique<int>(1);
int* ptr2 = ptr1.get();
// ...
// somewhere later:
std::unique_ptr<int> ptr3(ptr2);
// or std::unique_ptr<int> ptr3(std::move(ptr2));
In this case, the ownership of the int object is not transferred to the ptr3. It is erroneously assigned to it without releasing the ownership by ptr1. A programmer needs to be aware where the pointer passed to the std::unique_ptr constructor comes from, and how the ownership of the object has been enforced so far. An assurance by the library that it will invalidate this particular pointer variable may give the programmer a false sense of security, but does not provide any real safety.
I think the answer is simple: zero overhead. This change isn't needed for unique_ptr to be functional, so the standard doesn't require it. If you think this improves safety enough to worth it, you can ask your implementation to add it (maybe under a special compilation flag).
BTW, I'd expect static analyzers to know enough to warn against this code pattern.
Is that an accurate description of it? Does it make sense?
Are you guaranteed that the object it points to won't be deleted until the unique_ptr goes out of scope [even if you're not using the unique_ptr]?
Yes, std::unique_ptr follows the RAII design principle.
No, std::unique_ptr does not prevent other code from doing something stupid, like calling delete on a pointer that belongs to the unique_ptr. The unique_ptr itself will call a deleter1 on the object it owns when either:
it goes out of scope
or
the unique_ptr is reassigned (via operator= or reset) to point to a different object
One can also revoke unique_ptr's ownership of an object by moving to a different smart pointer, or using the release member function. This breaks the association between the object and the unique_ptr and unique_ptr will no longer clean up the object.
1 The default deleter will use either delete or delete [], depending on whether the target has array type. But unique_ptr is a template and its deleter can be customized, for example the cleanup operation for a FILE* can be chosen to be a call to fclose.
This capability can be used to schedule an arbitrary cleanup action to take place when the unique_ptr goes out of scope. RAII is used for keeping locks, closing files, and so forth -- clearly there would be major problems if the cleanup action were performed early just because the compiler didn't see any future usage of the smart pointer. Luckily the C++ object lifetime rules are completely deterministic (even the order of destruction for multiple automatic variables in the same scope is well defined), and you can count on the smart pointer cleaning up its owned object exactly when the smart pointer is itself destroyed.
std::unique_ptr is RAII, as the creation of the object also initializes it.
Are you guaranteed that the object it points to won't be deleted until the unique_ptr goes out of scope [even if you're not using the unique_ptr]?
If you make a few assumptions:
You don't move the unique_ptr (that would cause the newly moved to location to be the one that will delete
You don't delete the pointer yourself or add it to another control structure.
Or put more succinctly, yes it will live that long.
It is an application of RAII, indeed.
But you are not granted that the object it points to is not deleted by someone else before the unique_ptr goes out of scope.
E.g.
int* p = new int;
int* cp = p;
std::unique_ptr<int> up(p);
delete cp;
will give undefined behavior.
std::unique_ptr can be used for RAII, but doesn't prevent you from doing something like this:
#include <memory>
class Foo{};
int main()
{
Foo* pFoo = new Foo;
std::unique_ptr<Foo> upFoo(pFoo);
delete pFoo; // WRONG, double deletion when upFoo's destructor is called
}
Usually, the best way to use smart pointers is to pass the raw pointer as their constructor or make-like function, such as
#include <memory>
class Foo{};
int main()
{
std::unique_ptr<Foo> upFoo(new Foo); // or make_unique in C++14
}
I am just learning about smart pointers, and I am having trouble assigning a pre-existing location of a variable to the standard library's shared pointer.
For example, lets say you have an int x, which you do not know the value of. With normal pointers, I just did
int* ptr;
ptr = &x;
I tried both that with shared pointers, and
std::tr1::shared_ptr<int> ptr;
ptr = std::make_shared<int> (&x)
So i'm fairly lost as to how to do it.
You wouldn't (usually) make a smart pointer point to an existing variable. A smart pointer manages the lifetime of a dynamically allocated object, deleting it after use; pointing it to something that wasn't dynamically allocated will cause an error if it tries to delete it.
You would usually use new or make_shared to create an object, and create or assign a smart pointer with the result of that:
std::shared_ptr<int> ptr(new int(42)); // Create a new pointer to manage an object
ptr.reset(new int(66)); // Reset to manage a different object
ptr = std::make_shared<int>(53); // Use `make_shared` rather than `new`
make_shared is usually preferable to new, since it makes better use of memory and gives stronger exception-safety.
Shared pointers are used to manage dynamically allocated memory and more precisely, they manage the ownership for this memory.
Basically, a smart pointer is a materialization of the Ressource Acquisition Is Initialization, or RAII. I strongly suggest you take a look at this principle, as it is extremely useful for managing resource ownership (basically, each time you need to acquire a resource, and release it, be it memory, a database connection, a file handler, a mutex, etc.).
What it does is basically guarantee that while someone points at the dynamically allocated memory it manages, then this memory will be available, and as soon as the last (smart) pointer to this memory goes out of scope, then delete is called.
Then, it makes no sense to use smart pointers with variable that have automatic storage duration (i.e. that are removed when they go out of scope or when the object they're member of goes itself out of scope or is deleted (if it was new'd).
You should not create a smart pointer pointing to an object that is not dynamically allocated. Otherwise the smart pointer may try to delete the allocated memory which in turn will cause an error.
as soon as the reference counter of the shared_ptr reaches zero, the object will be deleted by the last shared_ptr. with smart pointers you can specify the function which shall delete that object.
the Deleter is a simple function (defaults to the usual operator delete) that has to be bound to the smart pointer, either statically via template parameter (see unique_ptr) or dynamically via constructor parameter (see shared_ptr).
// dynamically via shared_ptr:
// shared_ptrs share the pointer to the Deleter
// because they already share a common data structure for reference counting.
auto ignore = [](int* o){
std::cout<<"i will refuse to delete this object: " << o << "\n";
std::cout<<"not my responsibility." <<std::endl;
};
std::shared_ptr<int> sptr(&x,ignore);
//statically via unique_ptr:
// actually, the unique_ptr is as data structure not more than a regular pointer.
// but a pointer with special copy-constructor and destructor,
// which will most likely be inlined.
// there is no space to store a reference to a Deleter dynamically.
struct IgnorantDeleter{
void operator()(int* o){
std::cout<<"who ate my cake? " << o << "\n";
std::cout<<"but i baked it." <<std::endl;
}
};
std::unique_ptr<int,IgnorantDeleter> uptr(&x);
I try to understand how std::unique_ptr works and for that I found this document. The author starts from the following example:
#include <utility> //declarations of unique_ptr
using std::unique_ptr;
// default construction
unique_ptr<int> up; //creates an empty object
// initialize with an argument
unique_ptr<int> uptr (new int(3));
double *pd= new double;
unique_ptr<double> uptr2 (pd);
// overloaded * and ->
*uptr2 = 23.5;
unique_ptr<std::string> ups (new std::string("hello"));
int len=ups->size();
What is confusing to me is that in this line
unique_ptr<int> uptr (new int(3));
We use integer as an argument (between round brackets) and here
unique_ptr<double> uptr2 (pd);
we used an pointer as an argument. Does it make any difference?
What is also not clear to me, is how pointers, declared in this way will be different from the pointers declared in a "normal" way.
The constructor of unique_ptr<T> accepts a raw pointer to an object of type T (so, it accepts a T*).
In the first example:
unique_ptr<int> uptr (new int(3));
The pointer is the result of a new expression, while in the second example:
unique_ptr<double> uptr2 (pd);
The pointer is stored in the pd variable.
Conceptually, nothing changes (you are constructing a unique_ptr from a raw pointer), but the second approach is potentially more dangerous, since it would allow you, for instance, to do:
unique_ptr<double> uptr2 (pd);
// ...
unique_ptr<double> uptr3 (pd);
Thus having two unique pointers that effectively encapsulate the same object (thus violating the semantics of a unique pointer).
This is why the first form for creating a unique pointer is better, when possible. Notice, that in C++14 we will be able to do:
unique_ptr<int> p = make_unique<int>(42);
Which is both clearer and safer. Now concerning this doubt of yours:
What is also not clear to me, is how pointers, declared in this way will be different from the pointers declared in a "normal" way.
Smart pointers are supposed to model object ownership, and automatically take care of destroying the pointed object when the last (smart, owning) pointer to that object falls out of scope.
This way you do not have to remember doing delete on objects allocated dynamically - the destructor of the smart pointer will do that for you - nor to worry about whether you won't dereference a (dangling) pointer to an object that has been destroyed already:
{
unique_ptr<int> p = make_unique<int>(42);
// Going out of scope...
}
// I did not leak my integer here! The destructor of unique_ptr called delete
Now unique_ptr is a smart pointer that models unique ownership, meaning that at any time in your program there shall be only one (owning) pointer to the pointed object - that's why unique_ptr is non-copyable.
As long as you use smart pointers in a way that does not break the implicit contract they require you to comply with, you will have the guarantee that no memory will be leaked, and the proper ownership policy for your object will be enforced. Raw pointers do not give you this guarantee.
There is no difference in working in both the concepts of assignment to unique_ptr.
int* intPtr = new int(3);
unique_ptr<int> uptr (intPtr);
is similar to
unique_ptr<int> uptr (new int(3));
Here unique_ptr automatically deletes the space occupied by uptr.
how pointers, declared in this way will be different from the pointers declared in a "normal" way.
If you create an integer in heap space (using new keyword or malloc), then you will have to clear that memory on your own (using delete or free respectively).
In the below code,
int* heapInt = new int(5);//initialize int in heap memory
.
.//use heapInt
.
delete heapInt;
Here, you will have to delete heapInt, when it is done using. If it is not deleted, then memory leakage occurs.
In order to avoid such memory leaks unique_ptr is used, where unique_ptr automatically deletes the space occupied by heapInt when it goes out of scope. So, you need not do delete or free for unique_ptr.
Unique pointers are guaranteed to destroy the object they manage when they go out of scope.
http://en.cppreference.com/w/cpp/memory/unique_ptr
In this case:
unique_ptr<double> uptr2 (pd);
pd will be destroyed when uptr2 goes out of scope. This facilitates memory management by automatic deletion.
The case of unique_ptr<int> uptr (new int(3)); is not different, except that the raw pointer is not assigned to any variable here.
From cppreference, one of the std::unique_ptr constructors is
explicit unique_ptr( pointer p ) noexcept;
So to create a new std::unique_ptr is to pass a pointer to its constructor.
unique_ptr<int> uptr (new int(3));
Or it is the same as
int *int_ptr = new int(3);
std::unique_ptr<int> uptr (int_ptr);
The different is you don't have to clean up after using it. If you don't use std::unique_ptr (smart pointer), you will have to delete it like this
delete int_ptr;
when you no longer need it or it will cause a memory leak.