Click here to Skip to main content
15,886,816 members
Articles / Programming Languages / C++

Using std::unique_ptr (RAII) with malloc() and free()

Rate me:
Please Sign up or sign in to vote.
4.57/5 (6 votes)
19 Sep 2014CPOL1 min read 25.3K   4   1
Using std::unique_ptr (RAII) with malloc() and free()

This is a short post about using std::unique_ptr with malloc() and free(). Although, it can be used with other resource management functions too (files, sockets, etc.).

Often, when working with legacy C and C++ code, we see usages of malloc() and free(). Just like new and delete, explicit memory management should be hidden in the guts of libraries whenever possible and never be exposed to the casual programmer.

It would be great if the legacy code could be easily changed to use std::make_unique() to make it nice clean and safe at the same time. Unfortunately, std::make_unique() uses new and delete operators internally. So, if our legacy code uses some custom functions to allocate and deallocate memory, then we may be forced to do more refactoring than we might have time for (e.g. to use new expressions instead of custom or malloc based allocators).

Luckily, we can still get the benefit of RAII by using std::unique_ptr by trading off some cleanliness.
But std::unique_ptr takes a deleter type. No problem, we have decltype() to the rescue!

C++
#include <memory>

int main()
{
    auto Data =
        std::unique_ptr<double, decltype(free)*>{
            reinterpret_cast<double*>(malloc(sizeof(double)*50)),
            free };
    return 0;
}

The decltype(free) gives back a function type of “void (void*)” but we need a pointer to a function. So, we say “decltype(free)*” which gives us “void (*)(void*)”. Excellent!

A bit awkward, but it is still nice, since it does RAII (automatic free) and both the allocator (malloc()) and the deallocator (free()) is clearly visible to the reader.

With decltype(), we don’t have to write our own deleter functor like in this example:

C++
#include <memory>

struct MyDeleter
{
    void operator()(double *p) { free(p); }
};

int main()
{
    auto Data =
        std::unique_ptr<double, MyDeleter>{
            reinterpret_cast<double*>(malloc(sizeof(double) * 50)) };
    return 0;
}

Also, with decltype(), we don’t have to spell out the type of the deleter like in this example:

C++
#include <memory>

int main()
{
    auto Data =
        std::unique_ptr<double, void(*)(void*)>{
            reinterpret_cast<double*>(malloc(sizeof(double) * 50)),
            free };
    return 0;
}

So, with std::unique_ptr, you can quickly hack RAII into legacy code. However, as a general guideline, prefer refactoring legacy code using modern C++.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Member 117485682-Jun-16 14:46
Member 117485682-Jun-16 14:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.