Instead of using try/catch blocks everytime I need to construct any objects after allocating a block of memory for them with an allocator I use internally in my container, I would like to use a class derived from std::auto_ptr (I have no c++11 here) with an overridden destructor, so that it could deallocate the pointed memory and release the pointer afterwards. Are there any disadvantages in doing this?
If you don't mind using boost and boost::shared_ptr<>, you can provide a custom deleter. See the top 2 answers to this question.
Related
I am working on a project where a couple of the classes overload operator new and delete to utilize free-lists and I tried to use make_shared to have my allocations managed by smart pointers when I realized that make_shared does not use the overloaded versions but makes an explicit call the global ::new. But according to this make_unique does use the overloaded versions. Which is quite baffling to me. Why does make_shared choose to ignore operator overloading but make_unique doesn't?
make_shared has to allocate two things: the object being constructed and the shared_ptr's control block. To improve performance, it allocates one chunk of memory big enough for both and then placement-news them.
make_unique doesn't need to do that since a unique_ptr doesn't need a control block.
If you want to control how memory is allocated for an object to be managed by a shared_ptr, create an appropriate allocator class and use allocate_shared instead of make_shared.
I'm totally new to C++. I would like to ask about the following.
If a member variable is dynamically allocated in the constructor. Should it always be deleted in destructor? If so, then how is the variable's lifetime "elongated"? If not, how should memory leak be handled otherwise?
I couldn't find any source to address this issue explicitly.
Reasons to allocate a member dynamically are
The size of an array may be non-constant
The member could be very large, such that there is not enough memory on the stack
The member is polymorphic, as commented by MSalters
But, as Alf already pointed out in a comment, it is preferable to use a smart pointer. This has the advantage that you don't need to explicitly delete that member in the destructor, and in the case of a shared_ptr, you can elongate the liftime as needed, the smart pointer takes care of the destruction.
Should it always be deleted in destructor?
Not a necessity - you can free up the memory as soon as the work is done by some other function, if you are sure it won't be used any further. But, you must anyway call this destruction routine from destructor also to avoid memory leak. Ideally, you'd also need to provide another function for ReAllocate the memory.
In short, it all depends on your class and what are you implementing.
Let me take some post-modern approach and say "you don't have to worry about it anymore"
use unique_ptr if only the creating-object is incharge of that resource, use shared_ptr if many objects share that resource. use STL containers for all other possible uses.
use new and delete only if you're writing something extremely low-level or implementing a container from scratch. for all other cases, view dynamic memory allocation (via malloc and new) as deprecated.
I want a vector to hold pointers to some objects that it will own.
Here is the vector:
private:
std::vector<fppVirtual*> m_fapps;
I have created elements like this:
m_fapps.push_back(new fpp1(renderingEngine)); //fpp* are subclasses of fppVirtual
m_fapps.push_back(new fpp2(renderingEngine));
m_fapps.push_back(new fpp3(renderingEngine));
As m_fapps is a vector instance variable in another class, I want to make sure that class's destructor properly cleans up m_fapps:
for (int i=0, size=m_fapps.size();i<size;++i){
delete m_fapps[i];
}
Is this acceptable memory management technique? I assume this loop is needed since when the vector goes out of scope when its owning class is destructed, only pointers to these new objects will be removed, right?
This works (with a few caveats) but is not considered idiomatic C++, for good reason.
You should strongly consider using a vector of smart pointers (or a smart vector like boost::ptr_vector) instead, in order to avoid having to do manual memory management.
This would also give you exception safety for free, and would also avoid nasty ownership issues that occur if your outer class is copyable.
As no one gave you straight forward answer yet - yes, it is acceptable and this is the only way to free this memory, having this declaration of the vector.
This can and should be avoided, using smart pointers, as #OliCharlesworth suggested or using some other container, ponited by #BjörnPollex.
You should use boost::ptr_vector instead. The interface is the same, but it handles memory management for you. See this question for some guidelines about whether to use ptr_vector or vector<shared_ptr<>>.
I am using few library functions that return a pointer created either using malloc or new.
So, I have my own customer deallocator based on what type of allocation was used.
E.g
shared_ptr<int> ptr1(LibFunctA(), &MallocDeleter); //LibFunctA returns pointer created using malloc
shared_ptr<int> ptr2(LibFunctB(), &newDeleter); //LibFunctB returns pointer created using new
Now, I understand this is a very naive use of deallocator above but what other scenarios is it heavily used for ?
Also, how can one use a customer allocator ? I tried to assign a custom allocator as below but now how do I actually get it called ? Where does this kind of feature help ?
shared_ptr<int> ptr3(nullptr_t, &CustomDeleter, &CustomAllocator); //assume both functs are defined somewhere.
I don't see anything "naive" about using deleters that way. It is the main purpose of the feature after all; to destroy pointer objects that aren't allocated using the standard C++ methods.
Allocators are for when you need control of how the shared_ptr's control block of memory is allocated and deleted. For example, you might have a pool of memory that you want these things to come from, or if you're in a memory-limited situation where allocation of memory via new is simply not acceptable. And since the type of the control block is up to shared_ptr, there's no other way to be able to control how it is allocated except with some kind of allocator.
Custom deleters for shared_ptr are very useful for wrapping some (usually) C resource that you need to later call a freeing function on. For example, you might do something like:
shared_ptr<void> file(::CreateFileW(...), ::CloseHandle);
Examples like this abound in C libraries. This saves from having to manually free the resource later and take care of possible exceptions and other nasties.
I think the custom allocator will be used to allocate space for the "shared count" object, that stores a copy of the deallocator (deleter) and the reference counter.
As for what a custom deleter can be used for...
One use was already mentioned: make shared_ptr compatible with objects that must be deleted by some special function (like FILE which is deleted by fclose), without having to wrap it into a helper-class that takes care of the proper deletion.
Another use for a custom deleter is pools. The pool can hand out shared_ptr<T> that were initialized with a "special" deleter, which doesn't really delete anything, but returns the object to the pool instead.
And one other thing: the deleter is already necessary to implement some shared_ptr features. E.g. the type that's deleted is always fixed at creation time, and independent of the type of the shared_ptr that's being initialized.
Vou can create a shared_ptr<Base> by actually initializing it with a Derived. shared_ptr guarantees that when the object is deleted, it will be deleted as a Derived, even if Base does not have a virtual dtor. To make this possible, shared_ptr already has to store some information about how the object shall be deleted. So allowing the user to specify a completely custom deleter doesn't cost anything (in terms of runtime performance), and doesn't require much additional code either.
There are probably dozens of other scenarios where one can make good use of the custom deleter, that's just what I have come up with so far.
I create a custom memory allocator like following:
class pool_allocator
{
// required methods
// ...
private:
boost::shared_ptr<MemoryChunks> m_t;
};
The purpose of this allocator is to share memory allocating by different container and only deallocate them when all container and deleted. therefore, I use boost::shared_ptr.
However after running it in VS2008, I detect a memory leak. I don't know why.
If I change boost::shared_ptr to MemoryChunks, the memory leak goes away.
Are you aware that allocators are treated as stateless in C++03? Try using your allocator in conjuntion with Boost.Containers (It was just accepted, but I think they are already part of Boost.Interprocess), which respects allocators. Not easy to say anything else without the definition for MemoryChunks.