I'm creating a gui api for games. I have for example a font for each widget in the form of a Font* . Right now I have it so that I do not ever manage the memory of these (for obvious reasons) because I think the user can use smart pointers if they want this memory managed. The con to this is that it is not very idiot proof. If a user set the font like this:
obj.setFont(new Font(""));
This would immediately cause a memory leak because no one ever frees it. The only way would be to delete getFont();
Would it be instead better for me to manage these?
Thanks
It's your decision if your library should take ownership of the resource, but whatever you choose, make it clear through the interface (and not only through comments or documentation).
In C++03, a good way to make it explicit that you are actually taking ownership is to receive the parameter as a std::auto_ptr : the client will have no doubt that he's transferring ownership
On the opposite, receiving a parameter through const reference should make it clear that you have no intention to ever delete the data (you can't possibly know if it has actually been new'ed in the first place).
Anyway, going for smart pointers would probably help with these questions.
It should be the responsibility of the caller to manage the memory of objects that are within the caller's scope.
That being said, in this case, you should really use smart pointers because they will deallocate themselves when they are no longer of use.
That's the problem with transferred ownership.
But: You can rewrite your interface to
void obj.setFont( SmartPtr<Font> font );
because then you are forcing the user to use a smart pointer.
Related
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.
I want to use C++11 Smart Pointers in new projects, and encounter a problem. Many current projects still use raw pointers as parameters in their interface and have no interface for smart pointers, e.g. QMainWindow::setCentralWidget.
To keep type consistent, I have to pass the stored pointer from get() like this segment:
QMainWindow win;
std::shared_ptr<QWidget> scrollArea{ std::make_shared<QScrollArea>() };
// QScrollArea is a derived class of QWidget.
win.setCentralWidget(scrollArea.get());
But I can't make sure whether other methods in Qt execute operator delete on the stored pointer of scrollArea.
Will it cause memory leak or other problems if some methods in Qt do that?
I've checked the latest C++ Standard CD and found nothing on that. Seems it's an undefined behavior.
If doing this is an undefined behavior and dangerous, is there a safe way to use smart pointer(s) with the interface for raw pointer(s)?
There's no such way in the general case. For each "legacy" interface you want to use, you must read its documentation to see how it interacts with ownership (which is what std smart pointers encapsulate). A single object can only be managed by one ownership scheme.
With Qt in particular, it's definitely not safe to mix smart pointers and Qt management. Qt's parent/child relationship between QObjects includes ownership semantics (children are deleted when their parent is), so you cannot safely mix this with any other ownership scheme (such as std smart pointers).
Note that the Qt docs you link to explicitly state that "QMainWindow takes ownership of the widget pointer and deletes it at the appropriate time."
Unfortunately, if you are using an interface that uses raw pointers, you will need to consult the documentation to determine if the method does or does not take ownership of the provided pointer.
If the function takes ownership, then you must invoke .release() to transfer the ownership to the function. If the function does not take ownership, then you would pass the object with .get().
Will it cause memory leak or other problems if some methods in Qt do that?
It won't introduce a memory leak, since the memory is afterall released. However, since both QT and the shared_ptr would call delete on that memory, you would likely get some nice heap corruption (UB in general).
is there a safe way to use smart pointer(s) with the interface for raw pointer(s)?
Sure. Don't have unrelated entities manage the same memory. For that it is adavantegous to use unique_ptr instead of shared_ptr when possible. With unique_ptr you could call .release() to release the memory from the control of the smartpointer, thus giving you the ability to give control over to QT.
Of course you need check the documentation to see when you have to manage memory yourself and when QT will do it for you.
I don't think you should be doing any deleting with the QWidget.
http://qt-project.org/doc/qt-4.8/qmainwindow.html#setCentralWidget
Note: QMainWindow takes ownership of the widget pointer and deletes it
at the appropriate time.
If you have to use smart pointers, you can use a weak_ptr which won't own or destroy it.
If you are using an interface which takes raw pointers, you already have the problem that you must know who is responsible for the lifetime of those pointers.
Adding shared_ptr into the mix doesn't change this.
If the interface will possibly delete the object, then you cannot use std::shared_ptr safetly. std::shared_ptr must control the lifetime of its objects and there's no way around this (without adding another level of indirection)
You can however get some use out of std::unique_ptr. If an interface will not delete a pointer, you can safetly pass in ptr.get(). If an interface takes ownership of the lifetime of that object, pass in ptr.release() and you give up controlling the lifetime yourself.
All in, you can get some usefulness out of smart pointers even with a legacy codebase, but you've got to be a little careful.
But I can't make sure whether other methods in Qt execute operator delete on the stored pointer of scrollArea.
If the widget has a parent, then the QT's memory management will release that object. In that case you must not use a smart pointer, because your application will try to release it twice, and that is an undefined behaviour.
The more I read about RAII, I understand that using the stack is the way to make sure that the code is exception safe.
Does that mean every time I am doing a new() in my code, I am doing something wrong in the sense there is a better way to do it using the RAII principle?
You're not necessarily doing something wrong if you use new, but it's worth checking that you're doing it right.
The result of the new expression should be immediately placed under the control of a smart pointer, usually by passing it straight into the constructor.
If that smart pointer is a shared_ptr, then you are probably doing it wrong. You should probably use make_shared instead. There are some situations where you shouldn't (use of weak_ptr to large objects), and some where you can't (C++03 without Boost).
If you use delete then you pretty much are doing it wrong, unless you are writing your own smart pointer class. And even then, your smart pointer might be able to use another smart pointer to save work.
This is not essential, but if you use new solely because the object is "too big for the stack", consider writing a class that acts as a handle to the object, using unique_ptr or scoped_ptr to manage it, so that from the user's point of view the objects they deal with are automatic variables. If you feel like it, you can extend this to the full PImpl idiom. Even if you don't want another class, consider a function that creates the object and returns a unique_ptr to it, which you can then call like auto foohandle = give_me_a_foo();. Then give_me_a_foo contains new, but other user code doesn't, and you encourage the practice of automatically stuffing things into RAII objects.
There are alternative resource-management strategies to RAII in C++, but you'd know about it if you were using them, and that would affect what counts as "wrong".
I think you have not fully grasp what RAII really means. Dynamic allocations, in the same way that other resources like files, connections to databases, etc. are needed in programs. RAII focuses on how to manage those resources, and the way to go is to have the resources managed by objects with automatic storage duration (either stack, or as a member of another object).
That does not mean that every resource must be allocated in the stack, but rather that if you allocate something in the heap, you should delegate the responsibility of managing that memory to an object that is in the stack.
Not at all. If the nature of the beast (the allocation requirements) is truly dynamic, eventually it is either going to come from a heap or some severe trickery on the stack pointer.
The best you can do is to use wrappings that scope-guard for you. (I can' tell you how often I use std::vector<> when i need a dynamic temp buffer that is scope protected). It is one of the most ideal reasons to use well maintained and designed libraries like STL, etc. And unlike C# or Java, its predictable, which has tremendous value when truly needed.
No, stack space is very limited so you don't want to put huge things on it, hence the term stack overflow. Also if you need an object to have a lifetime longer than your function, then you can't put it on the stack.
I'm a c++ newbie, my code currently new's up on the heap in several places without calling delete. I know I need to do something about this.
My typical usage is where I new up a class instance in another classes member method then the method returns the pointer to the object.
If i change the return types from MyType* to std::tr1::shared_ptr will this fix my code to not leak memory?
Thanks a lot.
Edit:
Also likewise, I currently store new'ed up objects as MyType* as a value in a std:map. This map is a private member to a class instance. If I simply change this to std::tr1::shared_ptr will this clear up these when it's owner (class) falls out of scope?
Thanks again
It's a reasonable band-aid, sure.
A shared pointer is a reference-counted pointer. So as long as one or more shared_ptrs exist pointing to an object, that object will be kept alive. The problem occurs if you have circular references. Then the reference count will never reach 0, and the object(s) will never be deleted.
So shared_ptr * still* require you to understand what you're doing and think about object ownership, as you always have to do in C++. But it simplifies some otherwise complex scenarios, where determining ownership is hard.
But the real fix to your problem is to:
minimize how much you allocate with new. Can the object instead be stored on the stack? Can the object be rewritten as a RAII class, so that a small wrapper object is allocated on the stack (or elsewhere with automatic storage duration), and which, through its constructors and destructors, manages a heap-allocated memory resource? Then, as long as that object exists, its allocated memory will be preserved, and once it is destroyed, it will delete its allocated memory.
when you allocate objects with new, put them in one of the smart pointer classes. shared_ptr is popular because it is the one that comes closest to looking like a garbage collector, but it isn't, and if you treat it as one and use it as an excuse to not think about memory management, then it won't work. Understand all the smart pointer classes (scoped_ptr and auto_ptr in C++03, or unique_ptr replacing both in C++11, shared_ptr and weak_ptr), and use the one that best fits your scenario.
think about ownership. Any time you allocate memory, you need to determine an owner, whose lifetime will control the lifetime of the memory allocation. Think about how long a lifetime your allocation needs, and have another object (whose lifetime is automatically managed, probably because it is on the stack) delete your memory when its destructor is called.
There's no quick and easy fix. The way to handle memory management in C++ is to avoid memory management. Delegate it out to your objects. If you're calling delete in your own code, you're doing it wrong. Often, you don't even need new, but if you do, assign ownership to a smart pointer immediately, and let that call delete for you.
As a rule of thumb, unless you're a library writer, you shouldn't write either new or delete. You should virtually never use raw pointers, and only when it is absolutely necessary, use smart pointers. Let your classes do the heavy lifting. Don't be afraid to put them on the stack, pass them by value, and let them handle their resources internally.
If you are new to C++ there are a few points with pointer management you need to understand and accept, regardless of whether you're using shared_ptr or not.
It is more than likely in your use of C++ you will need to use new and assign its return pointer to a class pointer that you have declared. I believe it is advisable to take the time to understand what is going on there, even if you write a small test program and watch the constructor execute in the debugger.
If you use classes like std::string, its constructors and destructor will do string pointer management for you, but I believe it is a good idea to understand what is going on behind the scenes in that class, if nothing more than reading the documentation.
As another example, you cannot use some classes, without a lot of detailed reading of the API, or you'll get problems. I once worked at company that used a commercial class package years ago. Someone had written a multi-threaded program using this package's thread pool class.
The documentation clearly said you can't just exit with outstanding threads. Yet I saw where the author of the program did not bother to synch up and shutdown all threads on exit, and wound up throwing exceptions, when their program exited. And this was on a commercial financial product.
My suggestion is don't look to get saved from performing pointer management. There are std classes like string that can reduce your headaches, but nothing will prevent problems other than your own diligence and testing.
As long as you understand how tr1 shared pointers work, yes.
Look at Boost C++ shared_ptr<> also - it might be more what you want.
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.