Smart pointers with a resource manager that lets objects "borrow" resources - c++

I am somewhat new to the smart pointer world of C++ 11. I have been doing memory management manually and decided to dive into smart pointers. However, there is somewhat of a confusion though when it comes to managers
I define a manager as
An object that owns and manages a set of objects. The objects are exclusively owned by the manager and it's the manager's responsibly to control their life cycle (ie. delete them). It dispenses the objects for use in other parts of the program, but does not give away ownership.
In other words, it lets other parts of the program borrow the resources it manages.
What I am a little bit confused about, is how to ensure ownership is preserved by the manager?
For instance, in a videogame, a 'Sprite' might request a 'Texture' from a texture manager. The sprite doesn't own the texture, it simply wants to use it. One way to do this, is to utilize a list of unique_ptrs. So I have:
std::list<std::unique_ptr<SpriteTexture>> _spriteTextureList;
This however doesn't work, because I cannot establish a weak_ptr to a unique_ptr. On the other hand, I can create a list of shared_pointers
std::list<std::shared_ptr<SpriteTexture>> _spriteTextureList;
This will allow me to dispense weak_ptr to other parts of the program. However, the issue is that a shared_pointer can be duplicated, breaking ownership apart to multiple pointers. This of course can be controlled if I never pass back a shared pointer, but doing this seems to be counter-intuitive for what a shared_ptr is meant to represent.
The third alternative would be to simply dispense shared_ptr. However, this is not useful because then the manager doesn't technically own the objects. If the manager removes a Texture out of it's list and something else has a shared_ptr to the Texture, then the texture wont be deleted.
In the ideal situation this should be just fine, because there should be no existing pointers to the Texture before the manager deletes it, but I can see this becoming a debugging hassle.
I definitely have a weak understanding of smart pointers. Maybe I am miss understanding how smart pointers are supposed to be implemented?
Any help is greatly appreciated!

If "it simply wants to use it", then SpriteTexture* is just fine. Normal pointers are fine, as long as they don't have ownership semantics associated with them.
Just use your first solution (std::unique_ptr) and dispense normal pointers obtained with get().
You just have to make sure there are no other parts of the code using such a pointer when the manager decides to get rid of the associated object, but that's the opposite problem to the one in your question. (You sort of implied this wouldn't be a problem in your application.)
A side note: I can't think of a reason to use a std::list to hold those smart pointers. I think std::vector should be your first choice, unless you have a specific reason not to use it here.

Related

How is a unique_ptr unique?

I know unique_ptrs cannot be copied only moved and they have no reference counting. But we can have two smart pointers that share a resource:
Foo* f = new Foo;
auto p1 = std::unique_ptr<Foo>(f);
auto p2 = std::unique_ptr<Foo>(f);
Now both of these classes share a pointer to *f. Also, I know this will eventually cause UB because we will be doing double delete but still: What do we really mean by a unique_ptr being "unique" if this is possible?
Beside the fact that I do not believe that this is wanted or portable behaviour, I think that a unique_ptr is also a statement to other people working on the same project.
From the reference:
std::unique_ptr is a smart pointer that retains sole ownership of an
object through a pointer and destroys that object when the unique_ptr
goes out of scope. No two unique_ptr instances can manage the same
object.
As I understand this, the behaviour of the sample you showed is actually not wanted and should not be used at all.
For people without knowledge of the subject (aka programming for dummies): What the OP does is like having two girlfriends, not knowing of each other. You're fine until they find out. When they do, and they definitely will, you'll probably wish you wouldn't have played with the fire.
To understand the terminology, you have to contrast unique_ptr and shared_ptr:
the former should be the sole responsible for managing the resource it points to
the latter should be sharing this responsibility with a set of peers
Often times, you will hear the term ownership to describe the responsibility of cleaning up.
Now, like many things in C++, you can attempt to subvert the system: only the intention is described, it's up to you to uphold your end of the bargain.
Your question is akin to,
How is a crescent wrench a wrench when I can use it to drive nails in
to the wall?
In other words, just because you can incorrectly use a tool to do something that shouldn't be done with it, doesn't mean it can't do what it was designed to do.
A unique_ptr is unique in the sense that you won't make copies of the pointer if you use it correctly. It ensures that there's only one controlling object, and that the controlled object is destroyed properly when the container is destroyed.
This is about ownership semantics:
Sole or unique ownership (e.g. std::unique_ptr and the old friend std::auto_ptr): only one pointer at a time owns an object.
Shared ownership (e.g. std::shared_ptr, boost::intrusive_ptr, linked_ptr): many pointers share the same object.
It's unique because, when used correctly, it represents a unique ownership model - only one pointer gives access to, and controls the lifetime of, an object. Compare this to shared_ptr, which represents a shared ownership model - more than one pointer can be used to access and manage the same object.
As you point out, you can break that model by messing around with dumb pointers (either keeping hold of the one used to initialise the smart pointer, or by using get() or similar to bypass the ownership model). As always, it's up to the programmer to be careful not to do the wrong thing with dumb pointers. There is nothing a smart pointer can do to control the use of dumb pointers.
Not wishing to put words in the OP's mouth, but I think the issue they may be raising might be to do with naming. Perhaps they are saying something like:
'Aaaaah! It makes no sense! The language is a work of lunacy! Lunacy, I tell you! Run! Run! Save yourselves!'.
If that's what the OP is hinting at then...
Rather than look for 'meaning' in C++ words and symbols, just try to remember their actual effects. eg 'unique' doesn't mean 'One only', even though it appears to mean exactly that, it merely has the effect of indicating that the ptr should be used in certain ways and not others. Similarly, 'Private' does not mean private, but has an effect on how something is shared. 'Static' things can move, and 'move' keeps things where they are to avoid copying them to a new location.
All you have to do is read the documentation forever, and accept the pain.
See also 'Alice Through The Looking-Glass'.

Create a non-owning shared_ptr?

I am pretty new to C++11 and am now working on improving my C++ skills by trying to avoid direct usage of pointers. I am trying to write a sprite manager that keeps track of previously loaded sprites and frees unused ones. I am trying to use shared_ptr (pointer to the bitmap) for this, but the manager also has to keep a shared_ptr to create the sprites with - so the reference count doesn't drop to 0. Can I somehow declare the "parent" shared_ptr in my manager non-owning so it doesn't count as a reference (and still create owning copies of that shared_ptr)?
Use a weak_ptr. That will solve your problem. You won't need to free them as they will be automatically freed. Use a lock on the weak_ptr to get an actual shared_ptr.
The use_count will also give you the current number of references.
shared_ptr are made to be owning. If you want a non-owning pointer at some part of your prgram use weak_ptr like so:
std::shared_ptr<Object> sp(new Object);
std::weak_ptr<Object>(sp);
You're trying to do a kind of "backseat driver" style of memory management; you want to use shared-ptr, but you also want to control when shared_ptr frees resources!
There are a couple of obvious things you could do here.
Just use shared_ptr and don't bother with any sort of memory management or resource ownership in your sprite manager class. Trust shared_ptr to do its job. If you need to know when a resource is destroyed, you can always use the observer pattern or the like, and have your resource class message the manager when it is destroyed. Of course, this means you can't ask your sprite manager to provide additional references to an existing sprite, which isn't so great.
Write your own smart pointer. It isn't necessarily trivial, but writing a resource-specific reference-counting smart pointer isn't rocket science (its a hell of a lot simpler than writing something like shared_ptr, for example). The manager can then terminate resources when there's only a single reference to them remaining (eg. its own reference).
Everyone else has already mentioned weak_ptr. Has all of the benefits of (1), only you can create additional shared_ptr instances referencing the same underlying resource.
You might also want to consider resource usage patterns, and the cost of loading resources. You may not necessarily want to destroy a resource as soon as your application stops referencing it; if it is requested again a second later, it might take some time to reload it. Lazily freeing resources when they've gone unused for a little while might be a better approach. Just a thought.

Usage of Smart Pointers as a Programming Standard?

More and more I hear, that I should use smart pointers instead of naked pointers, despite I have effective memory leak system implemented.
What is the correct programming approach on using smart pointers please? Should they really be used, even if I check memory leaks on allocated memory blocks? Is it still up to me? If I do not use them, can this be considered as programming weakness?
If the smart pointers(ex: std::auto_ptr) are strongly recommended, should I use them instead of every naked pointer?
You should use RAII to handle all resource allocations.
Smart pointers are just one common special case of that rule.
And smart pointers are more than just shared_ptr. There are different smart pointers with different ownership semantics. Use the one that suits your needs. (The main ones are scoped_ptr, shared_ptr, weak_ptr and auto_ptr/unique_ptr (prefer the latter where available). Depending on your compiler, they may be available in the standard library, as part of TR1, or not at all, in which case you can get them through the Boost libraries.
And yes, you should absolutely use these. It costs you nothing (if done correctly, you lose zero performance), and it gains you a lot (memory and other resources are automatically freed, and you don't have to remember to handle it manually, and your code using the resource gets shorter and more concise)
Note that not every pointer usage represents some kind of resource ownership, and so not all raw pointer usage is wrong. If you simply need to point to an object owned by someone else, a raw pointer is perfectly suitable. But if you own the object, then you should take proper ownership of it, either by giving the class itself RAII semantics, or by wrapping it in a smart pointer.
You can't just blindly substitute std::auto_ptr for every raw pointer. In particular, auto_ptr transfers ownership on assignment, which is great for some purposes but definitely not for others.
There is a real reason there are several varieties of smart pointers (e.g., shared_ptr, weak_ptr, auto_ptr/unique_ptr, etc.) Each fulfills a different purpose. One major weakness of a "raw" pointer is that it has so many different uses (and has that versatility largely because it does little or nothing to assist in any one purpose). Smart pointers tend to be more specialized, which means they can be more intelligent about doing one thing well, but also means you have to pick the right one for the job or it'll end up dong the wrong things entirely.
Smart pointers allows to define automatically the life-time of objects it refers to. That's the main thing to understand.
So, no, you shouldn't use smart pointers everywhere, only when you want to automate life-time of your objects instead of having, for example, an object managing those objects inside from birth to death. It's like any tool : it solves specific kind of problems, not all problems.
For each object, you should think about the life cycle it will go through, then choose one of the simplest correct and efficient solution. Sometimes it will be shared_ptr because you want the object to be used by several components and to be automatically destroyed once not used anymore. Sometimes you need the object only in the current scope/parent-object, so scoped_ptr might be more appropriate. Sometimes you need only one owner of the instance, so unique_ptr is appropriate. Maybe you'll find cases where you know an algorithm that might define/automate the lifetime of an object, so you'll write your own smart pointer for it.
For example of opposite case, using pools forbids you to use smart_ptr. Naked pointers might be a more welcome simple and efficient solution in this particular (but common in embedded software) case.
See this answer (from me) for more explainations : https://softwareengineering.stackexchange.com/questions/57581/in-c-is-it-a-reflection-of-poor-software-design-if-objects-are-deleted-manuall/57611#57611
Should they really be used, even if I check memory leaks on allocated memory blocks?
YES
The whole purpose of smart pointers is, it help you implement RAII(SBRM), which basically lets the resource itself take the responsibility of its deallocation and the resource doesn't have to rely on you explicitly remembering to deallocate it.
If I do not use them, can this be considered as programming weakness?
NO,
It is not a weakness but a inconvenience or unnecessary hassle to explicitly manage the resources by yourself if you are not using Smart pointers(RAII). The purpose of smart pointers to implement RAII is to provide efficient and hassle free way of handling resources and you would just not be making use of it if you are not using it. It is highly recommended to use it purely for the numerous advantages it provides.
If the smart pointers(ex: std::auto_ptr)are strongly recommended, should I use them instead of every naked pointer?
YES
You should use smart pointers wherever possible because simply there is no drawback of using them and just numerous advantages to use them.
Don't use auto_ptr though because it is already deprecated!! There are various other smart pointers available that you can use depending on the requirement. You can refer the link above to know more about them.
It's a tricky question, and the fact that there is currently a mode to
use smart pointers everywhere doesn't make things any easier. Smart
pointers can help in certain situations, but you certainly can't just
use them everywhere, without thinking. There are many different types
of smart pointers, and you have to think about which one is appropriate
in every case; and even then, most of your pointers (at least in typical
applications in the domains I've worked in) should be raw pointers.
Regardless of the approach, several points are worth mentionning:
Don't use dynamic allocation unless you have to. In many
applications, the only things that need to be allocated dynamically
are objects with specific lifetimes, determined by the application
logic. Don't use dynamic allocation for objects with value semantics.
With regards to entity object, those which model something in the
application domain: these should be created and destructed according
to the program logic. Irregardless of whether there are pointers to
them or not. If their destruction causes a problem, then you have an
error in your program logic somewhere (not handling an event correctly,
etc.), and using smart pointers won't change anything.
A typical example of an entity object might be client connection in a
server, is created when the client connects, and destructed when the
client disconnects. In many such cases, the most appropriate management
will be a delete this, since it is the connection which will receive
the disconnection event. (Objects which hold pointers to such an object
will have to register with it, in order to be informed of its
destruction. But such pointers are purely for navigation, and shouldn't
be smart pointers.)
What you'll usually find when people try to use smart pointers
everywhere is that memory leaks; typical reference counters don't
handle cycles, and of course, typical applications are full of cycles: a
Connection will point to the Client which is connected to it, and
the Client will contain a list of Connection where it is connected.
And if the smart pointer is boost::shared_ptr, there's also a definite
risk of dangling pointers: it's far to easy to create two
boost::shared_ptr to the same address (which results in two counters
for the references).
If the smart pointers(ex: std::auto_ptr) are strongly recommended, should I use them instead of every naked pointer?
In my opinion, yes, you should it for every pointer that you own.
Here are my ideas on resource management in C++ (feel free to disagree):
Good resource management requires thinking in terms of ownership.
Resources should be managed managed by objects (RAII).
Usually single ownership is preferred over shared ownership.
Ideally the creator is also the owner of the object. (However, there are situations where ownership transfer is in order.)
This leads to the following practices:
Make boost::scoped_ptr the default choice for local and member variables. Do keep in mind that using scoped_ptr for member variables will make your class non-copyable. If you don't want this see next point.
Use boost::shared_ptr for containers or to enable shared ownership:
// Container of MyClass* pointers:
typedef boost::shared_ptr<MyClass> MyClassPtr;
std::vector<MyClassPtr> vec;
The std::auto_ptr (C++03) can be used for ownership transfer. For example as the return value of factory or clone methods:
// Factory method returns auto_ptr
std::auto_ptr<Button> button = Button::Create(...);
// Clone method returns auto_ptr
std::auto_ptr<MyClass> copy = obj->clone();
// Use release() to transfer the ownership to a scoped_ptr or shared_ptr
boost::scoped_ptr<MyClass> copy(obj->clone().release());
If you need to store a pointer that you don't own then you can use a raw pointer:
this->parent = inParentObject;
In certain situations a boost::weak_pointer is required. See the documentation for more information.
In general you should prefer smart pointers, but there are a couple of exceptions.
If you need to recast a pointer, for example to provide a const version, that becomes nearly impossible with smart pointers.
Smart pointers are used to control object lifetime. Often when you are passing a pointer to a function, the function will not affect the lifetime; the function does not try to delete the object, and it does not store a copy of the pointer. The calling code cannot delete the object until the function returns. In that case a dumb pointer is perfectly acceptable.
Yes. Assuming you have C++0x available to you, use unique_ptr or shared_ptr (as appropriate) to wrap all the raw pointers you new up. With the help of make_shared, shared_ptr is highly performant. If you don't need reference counting then unique_ptr will get you better perf. Both of them behave properly in collections and other circumstances where auto_ptr was a dumb pointer.
Using smart pointers (shared_ptr or otherwise) EVERYWHERE is a bad idea. It's good to use shared_ptr to manage the lifetime of objects/resources but it's not a good idea to pass them as parameters to functions etc. That increases the likelihood of circular references and other extremely hard to track bugs (Personal experience: Try figuring out who should not be holding onto a resource in 2 millions lines of code if every function invocation changes the reference count - you will end up thinking the guys who do this kind of thing are m***ns). Better to pass a raw pointer or a reference.
The situation is even worse when combined with lazy instantiation.
I would suggest that developers should know the lifecycle of the objects they write and use shared_ptr to control that (RAII) but not extend shared_ptr use beyond that.

Should I convert shared_ptr to weak_ptr when passed to a method?

there are already a couple of questions regarding this topic, but I am still not sure what to do: Our codebase uses shared_ptr at many places. I have to admit that we did not define ownership clearly when writing it.
We have some methods like
void doSomething(shared_ptr<MyClass> ptr)
{
//doSomething() is a member function of a class, but usually won't store the ptr
ptr->foo();
...
}
After having discovered the first (indirect) circular dependencies I would like to correct the mistakes in our design. But I'm not exactly sure how. Is there any benefit in changing the method from above to
void doSomething(weak_ptr<MyClass> ptr)
{
shared_ptr<MyClass> ptrShared = ptr.lock();
ptrShared->foo();
...
}
?
I am also confused because some people say (including the Google Style guide) that in the first place it's important to get ownership correct (which would probably mean introduction of many weak_ptrs, e.g. in the example with the methods above, but also for many member variables that we have). Others say (see links below) that you should use weak_ptr to break cyclic dependencies. However, detecting them is not always easy, so I wonder if I really should use shared_ptr until I run into problems (and realize them), and then fix them??
Thanks for your thoughts!
See also
shared_ptr and weak_ptr differences
boost::shared_ptr cycle break with weak_ptr
boost, shared ptr Vs weak ptr? Which to use when?
We did not define ownership clearly.
You need to clearly define who owns what. There's no other way to solve this. Arbitrarily swapping out some uses of shared_ptr with weak_ptr won't make things better.
There is no benefit in changing your design above from shared_ptr to weak_ptr. Getting ownership right is not about using weak_ptrs, it's about managing who stores the shared_ptr for any significant length of time. If I pass a shared_ptr to a method, assuming I don't store that shared_ptr into a field in my object as part of that method, I haven't changed who owns that data.
In my experience the only reason for using weak_ptr is when you absolutely must have a cycle of pointers and you need to break that cycle. But first you should consider if you can modify your design to eliminate the cycle.
I usually discourage mixing shared_ptr's and raw pointers. It inevitably happens (though it probably shouldn't) that a raw pointer needs to be passed to a function that takes a shared_ptr of that type. A weak_ptr can be safely converted to a shared_ptr, with a raw pointer you're out of luck. Even worse, a developer inexperienced with shared_ptr's may create a new shared_ptr from that raw pointer and pass it to the function, causing that pointer to be deleted when the function returns. (I actually had to fix this bug in production code, so yes it does happen :) )
It sounds like you have a design problem. shared_ptr provides
a simple to use implementation for specific design solutions,
but it (nor anything else) can replace the design. Until you
have determined what the actual lifetime of each type of object
should be, you shouldn't be using shared_ptr. Once you've done
that, most of the shared_ptr/weak_ptr issues should disappear.
If, having done that, and determined that the lifetime of some
objects does depend on that of other objects, and there are
cycles in this dependency, you have to determine (at the design
level, again) how to manage those cycles---it's quite possible,
for example, that in those cases, shared_ptr isn't the correct
solution, or that many of the pointers involved are just for
navigation, and should be raw pointers.
At any rate, the answer to your question resides at the design
level. If you have to ask it when coding, then it's time to go
back to design.
Some people are right: you should at first have very clear picture about objects' ownership in your project.
shared_ptrs are shared, i.e. "owned by community". That might or might not be desirable. So I would advise to define ownership model and then to not abuse shared_ptr semantics and use plain pointers whenever ownership should not be "shared" more.
Using weak_ptrs would mask the problem further rather than fix it.

Getting started with smart pointers in C++

I have a C++ application which makes extensively use of pointers to maintain quite complex data structures. The application performs mathematical simulations on huge data sets (which could take several GB of memory), and is compiled using Microsoft's Visual Studio 2010.
I am now reworking an important part of the application. To reduce errors (dangling pointers, memory leaks, ...) I would want to start using smart pointers. Sacrificing memory or performance is acceptible as long as it is limited.
In practice most of the classes are maintained in big pools (one pool per class) and although the classes can refer to each other, you could consider the pool as owner of all the instances of that class. However, if the pool decides to delete an instance, I don't want any of the other classes that still refers to the deleted instance to have a dangling pointer.
In another part I keep a collection of pointers to instances that are delivered by other modules in the application. In practice the other modules maintain ownership of the passed instance, but in some cases, modules don't want to take care of the ownership and just want to pass the instance to the collection, telling it "it's yours now, manage it".
What is the best way to start introducing smart pointers? Just replacing pointers [at random] with smart pointers doesn't seem a correct way, and probably doesn't deliver all the (or any of the) advantages of smart pointers. But what is a better method?
Which types of smart pointers should I further investigate? I sometimes use std::auto_ptr for the deallocation of locally allocated memory, but this seems to be deprected in C++0x. Is std::unique_ptr a better alternative? Or should I go straight to shared pointers or other types of smart pointers?
The question Replacing existing raw pointers with smart pointers seems similar but instead of asking how easy it is, I am asking what the best approach would be, and which kind of smart pointers are suited best.
Thanks in advance for your ideas and suggestions.
I recommend using unique_ptr when possible (this may require some program analysis) and shared_ptr when this is impossible. When in doubt, use a shared_ptr to maximize safety: when handing off control to a container, the reference count will simply go to two and then back to one and the container will eventually delete the associated object automatically. When performance becomes an issue, consider using boost::intrusive_ptr.
Here are the 3 varieties found in the new C++11 standard (unique_ptr replaces auto_ptr)
http://www.stroustrup.com/C++11FAQ.html#std-unique_ptr
http://www.stroustrup.com/C++11FAQ.html#std-shared_ptr
http://www.stroustrup.com/C++11FAQ.html#std-weak_ptr
You can read the text for each pointer and there is an explanation of when to use which in there. For local memory management unique_ptr is the choice. It is non-copyable but movable so as you move it around the receiver takes ownership of it.
Shared_ptr is used if you want to share an object instance around with no one really owning the object and to make sure it doesn't get deleted while someone still has a reference to it. Once the last user of an object destroys the shared_ptr container, the contained object will be deleted.
weak_ptr is used in conjunction with shared_ptr. It enables one to "lock" to see if the reference shared_ptr object still exists before trying to access the internal object.