Why the code below do not works?
class A {};
void f(A* a) {
shared_ptr<A> c(a);
}
int main() {
auto a = make_shared<A>();
auto b = a.get();
f(b);
return 0;
}
In the end of the scope of f, my program crashes. What could be causing this? Is there something that's trying to be deleted and does not exists?
You have two unrelated shared pointers that are both trying to manage the same resource. That leads to undefined behaviour. In particular, they're both going to try to delete the resource when they go out of scope.
In general, just don't do this :)
class A {};
void f(A* a) {
shared_ptr<A> c(a);
}
int main() {
auto a = make_shared<A>();
auto b = a.get();
f(b);
return 0;
}
What's happening here is that your initial make_shared() is creating a shared_ptr which owns A. When you call f(b), you are creating a second, unrelated shared pointer which also thinks it owns the same data. When the function call f() ends, the local shared ptr variable is destroyed; this checks whether the reference count is zero (which it will be), and so deletes the object. Then, when the main function ends, the destructor for the local variable a runs, checks that the reference count is zero (again, it will be), and so tries to delete the same data a second time. This double-delete is what is causing the crash.
There are a couple of solutions to this: the easiest is simply not to deal with raw pointers, and pass the shared_ptr directly to f(). Then the reference counting will work correctly and the data will only be destroyed once.
Another way of doing this is to have your class A publicly inherit from std::enable_shared_from_this. Then you can use the shared_from_this() method to "recover" a shared pointer (with correct reference counting) from a raw pointer, i.e.
class A : public std::enable_shared_from_this<A> {};
void f(A* a) {
shared_ptr<A> c = a->shared_from_this();
}
You can read about enable_shared_from_this here.
Related
I am trying to understand the preferred approach for a class to handle the validity of (reference to) the object of another class.
In here, C has a vector that stores references of D objects. If D and C are a part of the library, how should C handle the case where a D object goes out of scope in the caller?
A couple approaches that I have in mind though not sure of the feasibility:
D knows about what _list stores and as soon as the said D goes out of scope, ~D() runs which removes itself from _list.
_list stores weak_ptr instead of a raw and upon any access to D, you invoke weak_ptr::lock() prior to accessing, though this will require the instantiation of a shared_ptr which seems to be not so common in production?
struct D
{
~D()
{
printf ("~D()\n");
}
};
class C
{
vector<D*> _list;
public:
void add(D* dObject)
{
_list.push_back(dObject);
printf ("Adding D => size = %ld\n", _list.size());
}
~C()
{
printf ("~C()\n");
}
};
int main()
{
C c1;
{
D d1;
c1.add(&d1);
}
/**
_list[0] is garbage now. How to avoid accessing it i.e
C being aware to not access it?
*/
printf ("----out of scope---\n");
D d2;
c1.add(&d2);
}
Alternatives are
Using scope_exit (also called scope guard):
int main() {
C c1;
{
D d1;
c1.add(&d1);
scope_exit d1_erase([&] {
c1.erase(&d1);
});
// ... insert here other code within the inner scope
}
// ... insert here other code within the outer scope
return 0;
}
You should use a std::set instead of a std::vector within D to more efficiently find and erase entries again. And of course D should publicly provide an erase or delete function.
scope_exit is part of the soon-to-be-published C++ Library Fundamentals v3 Technical Specification (https://en.cppreference.com/w/cpp/experimental/scope_exit). The implementation belonging to the accepted proposal is here: https://github.com/PeterSommerlad/SC22WG21_Papers/tree/master/workspace/P0052_scope_exit.
Creating a custom class managing adding and automatically deleting (also at scope exit) the pointer to and from the list from outside both classes:
class E
{
public:
E(C& c, D* dp) : _c(c), _dp(dp) { _c.add(_dp); }; // add to list
~E() { _c.erase(_dp); }; // remove from list
E(const E&) = delete; // rule-of-3
E& operator=(const E&) = delete;
private:
C& _c;
D* _dp;
};
int main() {
C c1;
{
D d1;
E e(c1, &d1); // adds pointer to d1 to c1 list
// and removes it automatically at the end of the scope
}
return 0;
}
You could also store D within E instead of referring to it by stored reference.
BTW: Destruction order for local scopes is in reverse order to construction.
Those two solutions keep C and D as they are. You have to decide yourself, whether C intrusively should have knowledge of its D object or whether its addition and removal from D is handled non-intrusively like in those two solutions.
I would not use a shared_ptr/weak_ptr for those cases, where the objects are stored locally and the time of destruction is clear (when leaving scope either at its end or due to an exception or a return statement).
Basically in c++, you should not keep any reference of the stack instance to some containers. It is dangerous with dangling memory accesses and you should add instances which is created on heap to your preferred container. In this case of, shared_ptr is useful and safe for managing the lifetime of your instance.
#include <vector>
#include <string>
#include <memory>
using namespace std;
struct D{
public:
string _name;
D(const string& name) : _name(name){}
~D(){
printf("~D()\n");
}
};
class C{
vector<shared_ptr<D>> _list;
public:
void add(shared_ptr<D> dObject){
_list.push_back(dObject);
printf("Adding D => size = %ld\n", _list.size());
}
void print() {
for (const auto& d : _list) {
printf("%s\n", d->_name.c_str());
}
}
~C(){
printf("~C()\n");
}
};
int main(){
C c1;
{
c1.add(make_shared<D>("first D"));
}
c1.add(make_shared<D>("second D"));
c1.print();
}
output:
Adding D => size = 1
Adding D => size = 2
first D
second D
~C()
~D()
~D()
Additional: remove an object by block scope
C c1;
{
auto d = make_shared<D>("first D");
shared_ptr<nullptr_t> D_deleter{ nullptr, [&](auto) { c1.remove(d); } };
c1.add(d);
} // d would be deleted here
Essentially, the original question is asking: "how do I know when a local variable goes out of scope?"
The answer is: when its destructor is called.
For the code in your question, you could have ~D() to remove itself from c1.
This is awkward, and the discussion beneath the question brings up std::shared_ptr,
but the code in the example uses a local variable. You can't use std::shared_ptr
on a local variable, only on a heap variable. This is not made clear in the discussion.
Here are two references to questions specifically related to shared_ptr and local variables:
Create shared_ptr to stack object
and
Set shared_ptr to point existing object
A better solution to your problem is to not use a local variable, but a heap variable.
The difference between local and heap variables seems to be causing some confusion.
C++ has several storage classes for variables:
stack - used for local variables and function parameters
register - sometimes used for local variables - primarily an optimization
global/static - "one and only one", in space allocated at program load time.
thread local - global/static but thread specific - each thread has its own copy.
heap - allocated by the program, on the fly, via new or malloc (or equivalent). Sometimes called "free store".
C++ has some tricks with new and delete where you can use a custom heap,
which is memory you're managing yourself, but that memory will have been allocated
from the general heap, or possibly exist inside other variables.
Here are three different examples:
A local variable:
void some_function(C& c1)
{
D d1;
c1.add(&d1);
}
When this function exits, the stack frame that contains d1 goes away,
and the variable ceases to exist. ~D() will get called,
and you could remove d1 from c1 if you added
a mechanism to do this, like making d1 hold a pointer to c1, etc.,
which is awkward, but possible.
std::shared_ptr will not help with a local variable.
A heap variable allocated with new:
void some_function(C& c1)
{
D *d1p = new D();
c1.add(d1p);
}
When this function exits, the D variable that d1p points to still exists.
It will continue exist until it is explicitly deleted. In this context,
the c1 variable "owns" this pointer, and it responsible for deleting it
when it has finished using it.
This is the case where adding a smart pointer can simplify reference management,
as in:
A heap variable and shared_ptr created via make_shared:
void some_function(C& c1)
{
std::shared_ptr<D> d1p = std::make_shared<D>();
c1.add(d1p);
}
This example creates a D variable on the heap, and creates a local shared_ptr
holding a reference to that D variable, via a small counter object,
which is also on the heap. When the shared_ptr is passed to the C::add method,
the reference count in the counter object is incremented. When the shared_ptr
goes out of scope, the reference count in the counter object is decremented.
The shared_ptr in the c1 object now holds the only reference to that shared_ptr,
and when the c1 object is destroyed, the shared_ptr it contains will be destroyed,
releasing its reference - if the count goes to zero, the object it points to will
also be destroyed.
Besides this automatic destruction, another advantage of this approach is that you can get references to this D variable
from c1 and use them elsewhere, and these references (and the D variable itself)
can outlive c1.
The C class has to be modified for this case, e.g.
std::vector<std::shared_ptr<D>> _list;
and
void add(std::shared_ptr<D> dObject)
Here's a reference to how shared pointers work:
How do shared pointers work?
and some documentation on make_shared:
https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared
I've stared using smart pointer and trying to wrap my head around best uses for it. I've read plenty of articles but I'm confused on which to use in the following example. I've included a shared_ptr and unique_ptrexamples to show what I'm trying to accomplish:
class A
public:
A();
private:
unique_ptr<B> ptrB;
unique_ptr<SomeObject> ptrUnique;
shared_ptr<SomeObject> ptrShared;
A::A()
{
ptrB(new B());
ptrUnique(new SomeObject());
ptrB->PassUnique(ptrUnique);
ptrShared(new SomeObject());
ptrB->PassShared(ptrShared);
}
class B:
public:
void PassUnique(unique_ptr<SomeObject> &ptr_unique);
void PassShared(weak_ptr<SomeObject> &ptr_weak);
void DoSomething();
private:
unique_ptr<SomeObject> ptrUnique;
weak_ptr<SomeObject> ptrWeak;
B::PassUnique(unique_ptr<SomeObject> &ptr_unique)
{
ptrUnique = ptr_unique;
}
B::PassShared(weak_ptr<SomeObject> &ptr_weak)
{
ptrWeak = ptr_weak;
}
B::DoSomething()
{
ptrUnique->SomeMethod();
shared_ptr<SomeObject> ptr1 = ptrWeak.lock();
ptr1->SomeMethod();
}
SomeObject class can be any class. A good example is a database handle that I pass from the parent class A were it was originally initiated to multiple class like B. And from B to C if it exists. My question is if I'm passing a unique_ptr as a reference will setting for example ptrUnqiue = ptr_unique in B:PassUnique create a copy which then is not correct? Or should this be done via shared_ptr? This understanding is what is confusing with smart pointers for me and would appreciate clarification.
Well, this is a question of lifetime. Do you need SomeObject to outlive A? Do B send or is being use outside of this context? You have to decide when your objects dies. If you think SomeObject exists only in this context, I would recommend A to be the owner, as it allocate the resource, and be to old a raw pointer to SomeObject. I would look like this:
class A
public:
A();
private:
unique_ptr<B> ptrB;
unique_ptr<SomeObject> ptrUnique;
};
A::A()
{
ptrB(new B());
ptrUnique(new SomeObject());
ptrB->PassUnique(*ptrUnique);
}
class B:
pubic:
void PassUnique(SomeObject& obj);
void DoSomething();
private:
SomeObject* ptrUnique;
};
B::PassUnique(SomeObject& obj)
{
ptrUnique = &obj;
}
B::DoSomething()
{
ptrUnique->SomeMethod();
}
There is no such thing as
ptrUnique = ptr_unique;
If you need SomeObject to be used and owned outside of this structure, then go with std::shared_ptr like you did. There were no errors with your std::shared_ptr code.
Answer is basically what would be a lifetime of the pointer in the A, B and/or C. Think of it as ranges, [A...a), [B...b) and [C...c). If [B...b) is always within [A...a) and [C...c) is always within [B...b), they have like a Russian dolls hierarchy, then passing down ref-to-ptr is ok. If ranges overlap and changes wildly so you don't really control where last ptr will be destructed and object will be deleted, you'd have to go with shared_ptr.
Suppose I have the following code, which is a simplified example of my problem:
#include <string>
#include <iostream>
#include <memory>
class A{
public:
std::string name() { return "class A"; }
};
class B{
public:
B(){
m_a = std::make_shared<A>();
}
std::shared_ptr<A> get_a() { return m_a; }
private:
std::shared_ptr<A> m_a;
};
std::shared_ptr<A> foo()
{
B b;
return b.get_a();
}
int main()
{
auto a = foo();
auto name = a->name();
std::cout << name;
return 1;
}
I was wondering is it safe to do so? "b" which is an instance of B will be released at the end of function foo. "a" in the main function is a shared_ptr of B::m_a. Is it safe to use "a" after "b" is released?
Many thanks in advance!
That foo
shared_ptr<A> foo()
{
B b;
return b.get_a();
}
does not return a reference to a b member, but a standonly copy (of a copy, if not RV optimized) of the member; and the shared_ptr a
auto a = foo();
saves the A heap instance from destruction until scope end.
Thus I consider this safe, the Bs, although creators, are after all just one user of possibly many of the shared assets they create and publish.
In other words - the last one turns off the light, not the one who turned it on.
live at Coliru
Yes, it's safe. If this was not safe, then std::shared_ptr would be pretty useless.
"b" which is an instance of B will be released at the end of function foo.
Yes, but its std::shared_ptr<A> is copied before that.
Let's look at what the last line of the function really does:
return b.get_a();
get_a() produces a std::shared_ptr<A>, which is copied to a temporary object. This temporary std::shared_ptr<A> object is then copied again to become the result of the call in main.
(Actual copies may even be elided due to return-value optimisation, but that doesn't change anything. If anything, it makes the safety even easier to understand.)
Only then is b destroyed, but the std::shared_ptr<A> in it has already been copied by that time.
The std::shared_ptr<A> instance within b is destroyed, too, but the memory for the A object is not freed. That's the whole point of std::shared_ptr -- it knows how often it was copied and frees dynamically allocated memory only when the last copy is destroyed.
"a" in the main function is a shared_ptr of B::m_a.
No. It's a std::shared_ptr<A>, but that's it. It has nothing to do with the original B::m_a anymore.
Is it safe to use "a" after "b" is released?
Yes, because there is no lasting relationship between a and b.
Basically, you are questioning the safety a fundamental feature of C++, namely returning values from functions. Returning a std::shared_ptr is not different with regards to safety than returning a std::string or an int. That's always what happens when you return by value from a function: The to-be-returned value is copied, the original is destroyed, the copy lives on.
It is safe.
shared_ptr creates a tracked variable on the heap. This makes the object B more complex, as even when it is created on the stack, it allocates an A from the heap. Possibly impacting performance.
When all users of the tracked data have stopped accessing it, then the shared_ptr<> is deleted.
A question about boost::shared_ptr here:
I have 3 Classes.
A is some kind of Main class which is responsible to manage everything.
B is a class which just has functions to do some work.
Dispatcher is just a class which wraps around a seperate thread, which gets the work from Instaces of Bdone in this thread.
So it is kinda working like this: A has an instance of Dispatcher. Now on occassion A generates an instance of B and passes it to the dispatcher.
The important part is, that B needs to call A::callback() when it's done. This is why B gets a reference to A in it's constructor ( see code below )
A.hpp
class A : public boost::enable_shared_from_this<A>
{
public:
A();
void sendB();
void callback();
private:
Dispatcher m_Dispatcher;
};
B.hpp
class B
{
public:
B(boost::shared_ptr<A> ptr);
boost::shared_ptr<A> m_PointerToA;
/* Some other functions */
};
Dispatcher.hpp
class Dispatcher
{
public:
void run();
void dispatch(boost::shared_ptr<B> b);
private:
void doWork();
boost::thread m_Thread;
};
A.cpp
A::A()
{
m_Dispatcher.run();
}
void A::sendB()
{
boost::shared_ptr ptr_B;
ptr_B.reset(new B(this->shared_from_this);
m_Dispatcher.dispatch(ptr_B);
}
B.cpp
B::B(boost::shared_ptr<A> ptr) :
: m_PointerToA(ptr)
{
}
main_example.cpp
int main()
{
A instanceA;
while(true)
{
instanceA.sendB();
/* Do some other stuff */
}
return 0;
}
So my question is:
Is it reasonable to use boost::shared_ptr for this purpose?
I am not sure if the shared_ptr is the right thing to go here. My problem is, that I don't know what happens exactly when I call the constructor from B and pass it the this pointer. Now according to shared_ptr I would assume that m_PointerToA takes ownership of A. But this would mean that when the work in the Dispatcher is done and my instance of B gets deleted it would also delete the reference to m_PointerToA which would actually mean it kills the object itself despite the fact there is an actual instance of A in the main loop.
Update:
Added some code and updated question itself to make it more clear.
There's nothing particular wrong with this design. However I would prefer to instead use boost::function<> & boost::bind. It gives you way better flexibility for the callback and doesn't tie B as tightly to A. Of course you still have to be vary of the usual threading caveats.
Yes, it is okay to just copy/assign a shared_ptr, it will only increase the reference count.
In your example, shared_from_this() will create a (here: temporary) shared_ptr from the weak_ptr that is hold by this (ref count 1), so when you assign/copy-construct m_PointerToA, the reference count will increase temporarily to 2 before the ctor returns and the temporary object will be destroyed, decreasing the reference count to 1 again (the shared_ptr is "aware" of the one instance in your B object).
So, yes, if B is deleted, it will destroy A in this case (as the reference count drops to 0).
Your concern
This would mean if my Instance of B is deleted, it would also delete m_PointerToA which would also kill my instance of A . Of course my original instance of A is held elsewhere.
only shows that if you plan/need/intend to keep a pointer to the instance of A for further usage, you should do so with a shared_ptr as well instead of a raw pointer. If you have control of A's interface, the easiest way would be a named constructor like this:
class A : public boost::enable_shared_from_this<A> {
public:
static boost::shared_ptr<A> create();
void initClassB();
// ....
private:
A();
A( const A & other );
A& operator=( const A & rhs );
};
boost::shared_ptr<A> A::create() {
return boost::shared_ptr<A>( new A() );
}
Then, even if your instance of B is deleted, the instance of A will still survive because the reference count of the shared_ptr is still (at least) 1.
I need the flexibility of being able to change parameters passed around to different functions, depending from where the call to the function happened, so I decided I'd put all my parameters in a struct, however most of these parameters are structs or classes themselves and I want to have the option of leaving them NULL, so I have to pass pointers to the structs/classes.
struct A
{
otherB* b; // NULL should be a valid value
otherC* c;
};
However my question is now, passing A around these pointers will be the only thing copied, so if I did the following there would be a problem right?
void func(A& a) //non const cause I wanna change contents of A.
{
a.b = new b();
}
A myA;
otherC somec; // all these are currently automatic variables in my pgm.
myA.c = &somec;
func(myA); //myA goes out of scope? so I've lost all pointers assigned and since somec is out of scope too, I have a problem?
What would the best way to resolve something like this+ I want the flexibility of being able to pass NULL to any of my parameters, however not sure if using raw pointers everywhere is a good idea?
To solve the problem of resource management, you should use boost::shared_ptr (or std::shared_ptr in C++0x).
struct A
{
boost::shared_ptr< otherB > b;
boost::shared_ptr< otherC > c;
};
void func(A& a)
{
a.b = boost::make_shared< otherB >();
}
A myA;
otherC somec;
myA.c = boost::shared_ptr< otherC >(&somec, null_deleter());
func(myA);
When myA goes out of scope, all resources are deallocated automatically. Since somec was allocated on the stack, we wrapped it in a shared_ptr that uses a null_deleter, that could look like this:
struct null_deleter {
void operator()(void *) { }
};
This will not delete the object, it will do nothing (which is just what we want for stack-allocated objects). Keep in mind however, that you have to make sure that somec lives longer than myA, otherwise you will get access violations.
boost::optional<> Allows you to test if the field is set or not.
Simple example (will not compile, I've not even remotely tested it, in theory this is how it should work)
struct params
{
boost::optional<int> a;
boost::optional<foo> b;
boost::optional<bar> c;
};
void func(params& p)
{
if (p.a)
{
// do stuff with a
}
if (p.b)
{
// do stuff with b
}
if (p.c)
{
// do stuff with c
}
else
p.c = bar(); // again copy constructed and now initialized...
}
params p;
p.a = 1;
p.b = foo(); // copy constructed, however you can store a reference in the optional too.
// c is uninitialized
func(p);
// when p goes out of scope, everything is gone..
You basically have to analyze ownership, i.e. who can allocate and who is responsible for deleting object once they no longer is used.
One thing that is important to remember is that if you mix dynamically allocated things and things placed on the stack, you simply can't apply delete on them, as it's not possible to delete things on the stack.
One way could be to only use new and define a destructor in A that deletes all it's pointers. Another way could be a place where you would register objects that later should be deleted. Or you could go the route of using existing reference-counting tools, as suggested in other answers.
No, your idea of the scope of myA and somec are wrong. There's nothing wrong with what you have right now- although I personally think that references would be a superior option to pointers.
void func(A& a) //non const cause I wanna change contents of A.
{
a.b = new b();
}
int main() {
A myA;
otherC somec; // all these are currently automatic variables in my pgm.
myA.c = &somec;
func(myA);
// myA and somec are still perfectly in scope to be saved, or deleted, or w/e as you like
}
It's not clear from your description, but if you're having a problem
because somec is going out of scope, it can only be because func is
saving a copy of the pointer. Don't do that: in funct, copy the object,
not the pointer.
PS: if most of the pointers are null most of the time, you should
consider using something like following syntactic sugar:
struct A
{
// pointer members...
A() : // ... set all pointers to null...
A& withB( B const& someB ) { otherB = &someB; return *this ; }
A& withC( C const& someC ) { otherC = &someC; return *this ; }
// And so on for all of the rest of the pointers.
};
func( A().withC( somec ) );
Don't know if it's appropriate for your situation, but it's often
convenient.