Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using shared pointers with memory allocated in another function

Tags:

c++

c++11

I have some legacy-era code at work that takes in a double-pointer and allocates memory to it. A shortened example of it would look something like this:

struct LegacyObj
{
    int a;
    double b;
};

void LegacyAllocator(LegacyObj** ppObj)
{
    *ppObj = (LegacyObj*)malloc(sizeof(LegacyObj));
}

void LegacyDeleter(LegacyObj** ppObj)
{
    free(*ppObj);
}

The actual LegacyAllocator function is ~100 lines and mixes reading from files with creating a linked list of LegacyObj pointers, and isn't something I'd be able to get away with rewriting right now. I would like, however, to make the use of this function a bit safer, avoiding any memory leaks that may occur from exceptions &tc. The first solution I came up with was to wrap it up in a class and handle calling the legacy functions in the ctor/dtor.

class RAIIWrapper
{
public:
    RAIIWrapper()
        :obj{nullptr}
    {
        ::LegacyAllocator(&obj);
    }
    RAIIWrapper(RAIIWrapper&& that)
        : obj{ that.obj}
    {
        that.obj = nullptr;
    }
    RAIIWrapper& operator=(RAIIWrapper&& that)
    {
        RAIIWrapper copy{std::move(that)};
        std::swap(obj, copy.obj);
        return *this;
    }
    ~RAIIWrapper ()
    {
        ::LegacyDeleter(&obj);
    }

private:
    LegacyObj* obj;
};

But I'm curious - is there a way to do this using std::shared_ptr or std::unique_ptr? I've not been able to come up with a solution without having to keep the original pointer passed to LegacyAllocator around.

like image 392
The Forest And The Trees Avatar asked Dec 19 '13 15:12

The Forest And The Trees


1 Answers

Yes, you can use a custom deleter with std::unique_ptr or std::shared_ptr, for example:

struct Deleter {
  void operator()(LegacyObj *p) const {
    LegacyDeleter(&p);
  }
};

std::unique_ptr<LegacyObj, Deleter> MakeLegacyObj() {
  LegacyObj *p = 0;
  LegacyAllocator(&p);
  return std::unique_ptr<LegacyObj, Deleter>(p);
}

std::unique_ptr<LegacyObj, Deleter> p = MakeLegacyObj();

And, as correctly pointed out by @Dave, this works with shared_ptr too:

std::shared_ptr<LegacyObj> p = MakeLegacyObj();
like image 171
vitaut Avatar answered Nov 11 '22 01:11

vitaut