Are std::shared_ptrs aware of each other? - c++

That is, if I don't use the copy constructor, assignment operator, or move constructor etc.
int* number = new int();
auto ptr1 = std::shared_ptr<int>( number );
auto ptr2 = std::shared_ptr<int>( number );
Will there be two strong references?

According to the standard, use_count() returns 1 immediately after a shared_ptr is constructed from a raw pointer (ยง20.7.2.2.1/5). We can infer from this that, no, two shared_ptr objects constructed from raw pointers are not "aware" of each other, even if the raw pointers are the same.

Yes there will be two strong references, theres no global record of all shared pointers that it looks up to see if the pointer you're trying to cover is already covered by another smart pointer. (it's not impossible to make something like this yourself, but it's not something you should have to do)
The smart pointer creates it's own reference counter and in your case, there would be two separate ones keeping track of the same pointer.
So either smart pointer may delete the content without being aware of the fact that it is also held in another smart pointer.

Your code is asking for crash!
You cannot have two smart pointers pointing to the same actual object, because both will try to call its destructor and release memory when the reference counter goes to 0.
So, if you want to have two smart pointers pointing to the same object you must do:
auto ptr1 = make_shared<int>(10);
auto ptr2 = ptr1;

Related

how to monitor dangling pointers that points to leakded memory?

lets think we have a code like this :
int * ptr = new int;
int *nptr = ptr
int * ptr2 = new int;
int *nptr2 = 2*nptr+ptr2;
delete ptr;
delete ptr2;
ptr = NULL;
ptr2 = NULL;
So now the nptr and nptr2 is dangling pointer .I know that we can overload new allocating function to trace leaked memory (if we dont use delete command in code ) but dont know how to trace or monitor dangling pointers .
dangling pointers that points to leakded memory?
A pointer that has leaked, by definition is not being pointed by anything. A dangling pointer by definition points to memory that hasn't been leaked. This is a contradiction.
int *nptr2 = 2*nptr+ptr2;
This is ill-formed. Pointers cannot be multiplied by integers, and pointers cannot be added to pointers (I'm assuming the assumption is that result of the ill-formed multiplication is also a pointer). Furthermore, if this pointer arithmetic produced anything other than nptr, nptr+1, nptr2, nptr2+1, then the result would technically be undefined.
but dont know how to trace or monitor dangling pointers .
It's perfectly fine and normal to have dangling pointers. What isn't fine is indirecting through dangling pointers or relying on their value. At least for indirection, you can use an address sanitiser to try catch such bugs. It can find some uses of dangling pointers particularly those to dynamic memory such as the pointers in the question. It's not as good at detecting dangling pointers to automatic variables. On the other hand, compiler can catch simple cases such as returning pointer to local variable.
Alternatively, you can modify your program to use std::shared_ptr so that as long as you still hold a shared pointer, it cannot become dangling. This comes at a small cost of overhead, but it makes it much easier to reason about lifetime correctness.
First of all "dangling pointers that points to leakded memory" makes no sense. I suppose you mistakenly use "leaked memory" for objects that are already destroyed. In your code there is no memory leak. You have a memory leak when you do not have a pointer to some dynamically allocated obejct anymore, as in:
{
int* x = new int;
} // x goes out of scope, no way to delete the int
Further, it is not clear what this line is supposed to do int *nptr2 = 2*nptr+ptr2;. It is not valid C++, hence I am going to ignore it for the rest of the answer. Also the last two lines are not that relevant (maybe for code that comes after the shwon code but not here).
So we are left with:
int * ptr = new int;
int *nptr = ptr
int * ptr2 = new int;
delete ptr;
delete ptr2;
You create two int via new. You delete two int. No memory is leaked. After delete ptr the pointer nptr points to a no longer existing object. nptr is said to be a dangling pointer.
With that out of the way, we can turn to your actual question: How to monitor dangling raw pointers?
You cannot. A raw pointer is rather primitive. It stores an address. And thats all. The pointer is not aware whether there is an object at that adress or not. This is one reason you should not use new and delete and raw pointers to manage memory. Use smart pointers. For example if you share ownership between two std::shared_ptr then the pointee will be kept alive as long as one of the shared pointers is alive. A shared pointer cannot dangle (unless you do something wrong).
I would recommend that you not use raw pointers. If you use smart pointers that then you will never(*) have a dangling pointer. The whole purpose of smart pointers is to ensure that the lifetime of both the pointer and what is pointed to is managed together.
Use std::unique_ptr, std::shared_ptr (and std::weak_ptr if needed).
You can use tools like Valgrind and AddressSanitizer to ensure that you do not use dangling pointers.
(*) never is perhaps too strong, at least make it more difficult.

C++ multiple unique pointers from same raw pointer

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);

Smart pointers ownership semantics and equality

I have a couple of questions for smart pointers that earlier I didn't give them any credit.
What does mean to own an object , to point to a object and to manage a object in the world of smart pointers? Earlier I thought that the one who owns the object, also points to it and manages the object. Now, I know that a smart pointer can own an object, but point to another object (alias constructors). Here I found a really good explanation for what owning an object mean -> http://www.umich.edu/~eecs381/handouts/C++11_smart_ptrs.pdf , but still I can't make difference between this 3 terms.
If the pointer owns an object, but point to another object, which object does he manage? The one he owns it, or the one he points to, or both? What's the point of owning an object, but not pointing to it?
When are two smart pointers equal? Can two pointers own a same object and be different in a same time? I'm not interested in their value equality, but regarding the ownership.
Why is ownership order important (beside for using the pointers as keys in containers)? I guess this is relevant only for shared_ptr.
Everything began with trying to understand owner_before, now I'm more confused than before I began exploring this topic.. :(
I think all of your confusion comes from the "aliasing constructor":
template <typename U>
shared_ptr(const shared_ptr<U>& x, element_type* p)
What's the use of this thing? Well, it's rarely used, but what it does is to "share" ownership of some object x but when you dereference it you will get p instead. That's all. It will never delete p or do anything else to it.
It might be useful if you have something like this:
struct Foo {
Bar bar;
};
struct Baz {
Baz(shared_ptr<Bar> bar) : m_bar(bar) {}
shared_ptr<Bar> m_bar;
};
int main()
{
auto foo = make_shared<Foo>();
Baz baz(shared_ptr<Bar>(foo, &foo.bar));
}
Now baz gets to manage the lifetime of foo without knowing that's what it's doing--it only cares that it manages the lifetime of a Bar, but since our bar is part of foo, we can't destroy foo without destroying bar, so we use the aliasing constructor.
But actually, we don't do that, because this use case is very rare.
Old "raw" pointer:
someType* pR = new someType(param1, param2); //pR is a pointer
MyOwner.TakeOwnershipOf(pR); // Now MyOwner is the owner, **the one who ONLY should call 'delete pR;'**
Smart pointer:
std::shared_ptr<someType> sp = std::make_shared<someType>(param1, param2);
"sp" is now the owner (there's no "pR" in code, but internally it is). And you don't need to call "delete pR". It's an object that internally stores a pointer to pR and delete it when becomes no more needed.
sp is an object. "sp->any" is exactly as "pR->any". This can confusse you about sp being also a pointer. No, it happens that "->" is overloaded.
More overloaded:
sp.get() is the same as pR. *sp is the same as *pR
sp1 == sp2 is the same as pR1 == pR2 and the same as sp1.get()==sp2.get()
The good thing about shared_ptr is, for example, when you need to store the same pointer in several containers. If some container is deleted, the stored pointer (sp, who owns pR) should also be deleted. This will invalidate the pointer stored in other container. Instead of inspecting other containers about this pointer existence, shared_ptr takes in charge of it. This is, you can safely delete sp because pR will be only deleted by the last container that stores sp.
Ownership
Your confusion is because ownership is not something which the compiler can verify; you, as a programmer, need to deduce it.
We can say any object p owns q if the existence of p guarantees the existence of q (preferably without memory leaks).
The simple case is direct ownership, where deallocating p would also deallocate q, e.g. if q is a member of p, or q is explicitly deallocated with delete in p's destructor.
Smart pointers make this obvious to people. If q is stored in a std::unique_ptr member of p, we know that p owns q. You don't need to search around for the (possibly missing or duplicated) delete statement.
Ownership is also transitive, if p owns q and q owns r, then p must own r.
Aliasing
If p directly owns q, and we want to create a shared_ptr that owns q, then it must also own p. Otherwise, if p is destroyed, then q will be too, despite the existence of our shared pointer.
This is what the aliasing constructor for std::shared_ptr does (deomonstrated in John's answer).
It extends q's lifetime by extending p's lifetime, so we have a pointer to q which actually owns p. We are asserting to the compiler that p in fact owns q, so the shared ptr transitively owns q.
If p doesn't own q, then your program will compile, but it is broken, just like if you manually call delete twice.
Comparisons
For stl smart pointers, comparisons are passed to the raw pointer. So smart pointers are equal if they dereference to the same object, and comparisons are about memory location. There aren't any defined behaviors specifying memory locations, so there isn't much you can use it for other than storing in a map or set.

How to save an address to a smart_ptr

I wanted to ask like we can do with a pointer.
int q = 10;
int* p = &q;
How to do something with a shared_ptr? Can I use make_shared<> here?
shared_ptr<int> r = make_shared<int>(q);
Is this correct?
If you want a shared_ptr that owns a pointer, use the constructor directly:
std::shared_ptr<int> r(some_pointer_to_int);
If you want a shared_ptr that points to a copy of a given object, use make_shared:
auto r = std::make_shared<int>(some_int);
Note that the former would NOT be correct if the pointer points to an object with automatic storage duration. Such objects are managed by the runtime.
No it is not. Smart pointer is here for guaranteed deletion of the pointer(handle) around which it wraps. In your example you just take address of the local stack variable. Deletion of such a variable is undefined behavior(your app will crash most of the time).
But if your actual code is different and you truly want to keep an existing pointer(which is ok to delete later) in the shared_ptr you should do the following:
shared_ptr<int> r{q};
make_shared exists as a helper for creating shared_ptr passing arguments to the object the pointer is going to point to.
The point of smart pointers is to maintain their memory smartly. In your case q is located on the stack. If you pass it to a smart pointer then it will get deleted when it is no longer referenced. This will crash your program because you can't delete memory on the stack. It is also sort of silly to want to because it is freed when q goes out of scope anyway.
make_shared<>() takes the arguments to a constructor.
shared_ptr<int> r = make_shared<int>(q);
This constructs a shared point to a single int that holds the same value as q.
If you want to assign a pointer to a shared pointer you would do something like:
shared_ptr<int> r = q;
That being said, your particular example makes no sense. When the shared pointer goes out of scope it will call delete on a stack allocated variable with invokes undefined behavior.
Without any usage information it depends upon the lifetime. If you only need to use it during a function, you're better off with a reference.
auto& r = *q;
If you must get a pointer type you can do
auto& r = q;

question about smart pointers

I have this snippet of the code and I must write appropriate code with class A (constructor, destructor, copy constructor, operator =), my question is do I need write smart pointers if I want that this code will work perfectly, if no, can you explain where writing smart pointers will be useful, thanks in advance
A *pa1 = new A(a2);
A const * pa2 = pa1;
A const * const pa3 = pa2;
Smart pointer are most useful when it is difficult to predict when an object should be deleted. For example: if you create an object in one point, and the object might be delete in another very distant point, or more importantly, might be deleted by several different places, smart pointers is the best solution. So basically, unless you can say for sure when an object should be deleted, and it will always be safe to do so (i.e. no other object holds a pointer to that object) use smart pointers.
Another point of view, which some friends use, is that smart pointers are so cheap (i.e. the processing cost of using them is very small), smart pointer should always be used when objects are allocated on the heap (i.e. using new). That way, you'll never have to worry about memory leakage or double-frees, etc.
A smart pointer is not needed, as non of the operations following new can throw. You just need:
A *pa1 = new A(a2);
A const * pa2 = pa1;
A const * const pa3 = pa2;
delete pa1;
If this isn't what you are asking about, please clarify your question.