How to save an address to a smart_ptr - c++

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;

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.

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.

Are std::shared_ptrs aware of each other?

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;

c++, object created on the heap vs. local - when returning a pointer

This is a follow up question from
Safe in C# not in C++, simple return of pointer / reference,
Is this:
person* NewPerson(void)
{
person p;
/* ... */
return &p; //return pointer to person.
}
the same as?
person* NewPerson(void)
{
person* pp = new person;
return pp; //return pointer to person.
}
I know that the first one is a bad idea, because it will be a wild pointer.
In the second case, will the object be safe on the heap - and like in c#
go out of scope when the last reference is gone to it?
Yes, the second case is safe.
But the caller will need to delete the returned pointer. You could change this to use boost::shared_ptr and it will be destroyed when it is no longer in use:
boost::shared_ptr<person> NewPerson()
{
boost::shared_ptr<person> pp = boost::make_shared<person>();
return pp;
}
If C++11 then you can use std::shared_ptr or std::unique_ptr.
It's safe, the object will still be alive after the return.
But don't expect the object to be automatically cleaned up for you in C++. Standard C++ does not have garbage collection. You'll need to delete the object yourself, or use some form of smart pointer.
person* NewPerson(void)
{
person* pp = new person;
return pp; //return pointer to person.
}
I know that the first one is a bad idea, because it will be a wild
pointer. In the second case, will the object be safe on the heap - and
like in c# go out of scope when the last reference is gone to it?
Correct on the first one: it would be returning a pointer to data on that functin's stack, which will be reclaimed and modified once the function finishes.
On the second case: the object is created on the heap, which is separate from the execution stack. When the function finishes, the object on the heap is safe and stays the same. However, C++ does not automatically do garbage collection, so if you lost all of the references to a heap object, this would constitute a memory leak--the object's space would not be reclaimed until the program ended.
The latter is safe. However, C++ does not (usually) provide garbage-collection, and thus you need to arrange for an explicit delete of the returned object.
Like you say, the first case is bad as the pointer will not be valid. As for the second case, memory in C++ is not managed, you have to clean up after yourself. C++ doesn't keep track of references on normal pointer, that's what std::shared_ptr is for.

is this safe? (qt QQueue.dequeue() c++ inline pointer dereference)

Object object = *(queue.dequeue());
queue is a QQueue<Object*>. i'm concerned that the dequeued pointer is deleted before i dereference it. of course i can access object's data but that doesn't mean anything. doing it all in one line like this is convenient (i don't want a pointer because i want object to be deleted automatically when it goes out of scope) but if it's not safe then i can't do it. please advise. thanks.
It isn't immediately unsafe per se, but chances are you'll be using it wrong.
All your code does is make a copy of the element pointed to by the last element of queue. By dequeuing the element, you lose the pointer to it, and you now have no way of freeing that original object in case it was dynamically constructed.
Correct example (no dynamic objects, no leak):
QQueue<Foo*> q;
{
Foo a;
q.enqueue(&a);
Foo b = *q.dequeue();
}
Broken example (dynamic object leaked):
QQueue<Foo*> q;
q.enqueue(new Foo); // eeew, naked "new" in C++...
Foo c = *q.dequeue();
// now the newed element is leaked
You're right that c is safely destroyed at the end of its scope, but you're leaking the orginal, new'ed object, to which you have no pointer or reference now.