Using shared pointers with memory allocated in another function

c++, c++11

Solution

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();

Problem

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.

Original source