I'm in c++ and i'm writing a wrapper around a c library. The c library function i'm working with takes a type 'LDAPMessage **' as a parameter, where it will allocate the memory for you within the function. Normal usage looks like this:
LDAPMessage * msg;
c_lib_function(&msg); // allocates the memory for me
Now I want to use unique_ptr in this case, with a custom deleter. Assume my deleter 'LDAPMessageDeleter' exists and works in the following.
unique_ptr<LDAPMessage*, LDAPMessageDeleter> msg_ptr(new LDAPMessage*);
c_lib_function(msg_ptr.get());
Though this compiles for me, i'm getting a seg fault. Could this code be at fault here? Is this correct usage of unique_ptr?
Someone in the SO chat developed code valuely like this that I can no longer find:
And the usage of this
ptrptr
is quite simple:That's it. Real simple. http://coliru.stacked-crooked.com/a/644ed001ffd547ae
What happens is
ptrptr(my_ptr)
creates a temporaryptrptr_type
on the stack, which takes the pointer from theunique_ptr
. Theptrptr
then exposes a pointer to it's internal pointer, which the C function can freely modify. Afterwards, the temporaryptrptr_type
is destroyed, and its destructor puts the new value for the pointer back into the originalunique_ptr
.It might be easier to do e.g.
Of course, the
LDAPMessageDeleter
have to call the proper function to free the memory (e.g.free
is the memory was allocated withmalloc
).The problem with the code you show in the question, is that you try to create a pointer to a pointer, but don't make that first-level pointer actually point anywhere.
What you are effectively doing in your code is this:
What's happening in the C library, is that the pointer is passed "by reference". Since C doesn't actually have proper references, it's kind of emulated by passing pointers. And passing a "reference" to a pointer is done by using the address-operator to pass the address of the pointer (which then becomes a pointer to the pointer).
This isn't correct usage of the pointer-to-pointer. The function takes a pointer to uninitialized pointer and fills it. In your first example, this is a local variable. If you want it to be managed by
unique_ptr
, it should still be a local, just contained within theunique_ptr
object.LDAPMessageDeleter
should receive aLDAPMessage *
, and pass it to the library to be released if necessary, otherwise pass tofree()
.