Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you use a shared_ptr for RAII of C-style arrays?

I'm working on a section of code that has many possible failure points which cause it to exit the function early. The libraries I'm interacting with require that C-style arrays be passed to the functions. So, instead of calling delete on the arrays at every exit point, I'm doing this:

void SomeFunction(int arrayLength) {    shared_ptr<char> raiiArray(new char[arrayLength]);    pArray = raiiArray.get();     if(SomeFunctionThatRequiresCArray(pArray) == FAILED) { return; }     //etc. } 

I wanted to use unique_ptr, but my current compiler doesn't support it and the reference count overhead doesn't really matter in this case.

I'm just wondering if anyone has any thoughts on this practice when interfacing with legacy code.

UPDATE I completely forgot about the shared_ptr calling delete instead of delete []. I just saw no memory leaks and decided to go with it. Didn't even think to use a vector. Since I've been delving into new (for me) C++ lately I'm thinking I've got a case of the "If the only tool you have is a hammer, everything looks like a nail." syndrome. Thanks for the feedback.

UPDATE2 I figured I'd change the question and provide an answer to make it a little more valuable to someone making the same mistake I did. Although there are alternatives like scoped_array, shared_array and vector, you can use a shared_ptr to manage scope of an array (but after this I have no idea why I would want to):

template <typename T>     class ArrayDeleter     {     public:         void operator () (T* d) const         {             delete [] d;         }     };  void SomeFunction(int arrayLength)     {        shared_ptr<char> raiiArray(new char[arrayLength], ArrayDeleter<char>());        pArray = raiiArray.get();         if(SomeFunctionThatRequiresCArray(pArray) == FAILED) { return; }         //etc.     } 
like image 898
bsruth Avatar asked Jul 16 '10 15:07

bsruth


People also ask

When should you use a shared_ptr?

An object referenced by the contained raw pointer will not be destroyed until reference count is greater than zero i.e. until all copies of shared_ptr have been deleted. So, we should use shared_ptr when we want to assign one raw pointer to multiple owners. // referring to the same managed object.

Why would you choose shared_ptr instead of Unique_ptr?

In short: Use unique_ptr when you want a single pointer to an object that will be reclaimed when that single pointer is destroyed. Use shared_ptr when you want multiple pointers to the same resource.

Do you need to use smart pointers for Raii?

Smart pointers will use the RAII philosophy to ensure that heap allocated objects are destroyed any time the pointer variable is destroyed. In addition - pointers are the most common application of RAII - you'll likely allocate thousands of times more pointers than any other resource.

What is the difference between shared_ptr and Weak_ptr?

The only difference between weak_ptr and shared_ptr is that the weak_ptr allows the reference counter object to be kept after the actual object was freed. As a result, if you keep a lot of shared_ptr in a std::set the actual objects will occupy a lot of memory if they are big enough.


1 Answers

Do not use shared_ptr or scoped_ptr to hold pointers to dynamically allocated arrays. shared_ptr and scoped_ptr use delete ptr; to clean-up when the pointer is no longer referenced/goes out of scope, which invoked undefined behaviour on a dynamically allocated array. Instead, use shared_array or scoped_array, which correctly use delete[] ptr; when destructing.

To answer your question, if you are not going to pass the smart pointer around, use scoped_array, as it has less overhead than shared_array.

Alternatively, use std::vector as the array storage (vectors have guaranteed contiguous memory allocation).

like image 129
Jon Benedicto Avatar answered Oct 20 '22 02:10

Jon Benedicto