Embedded, Mbed OS & Smart pointers

Dear community –

With the team, we just set up SonarCloud for code analysis of our firmware and source code. The tool is really useful and helped us drastically improve our code base!

One code smell that is often found is the use of new. We usually make everything as static as possible, create objects before use, pass them as reference and avoid the use of new as much as possible (side question: is this a good practice?).

This is the actual code smell:

Memory should not be managed manually

The easy solution is the use of smart pointers: unique_ptr, shared_ptr and make_shared/unique.

Some of our code is based on mbed examples such as BLE that use new. We’ve replaced it with the aforementioned solutions and it works great, the binary is just slightly bigger.

That being said, we are wondering is it’s good practice to use smart pointers for embedded development in general and with mbed in praticular?

Thanks for you help and feedback on this matter :slight_smile:

Best,
– Ladislas

1 Like

And I don’t know how I missed that!

One code smell that is often found is the use of new . We usually make everything as static as possible, create objects before use, pass them as reference and avoid the use of new as much as possible (side question: is this a good practice?).

It is a good practice but like everything it depends on the context. For example, that would be terrible for networking stacks from a space perspective as not state can be reached at the same time and there is recovery path in case of failure due to OOM.

For the use of smart pointers, they are better than managing manually memory but it has a (small) cost in term of space. Mbed has been built on C++03 which wasn’t properly equipped to describe a unique_ptr (some hacks were possible though) but offered a stripped down version of SharedPtr very early.

But Smart pointer are not limited to managing memory. They are great to make a C API play well with RAII. Consider the following example:

#include <memory>
#include <stdio.h>

struct FileHandledeleter { 
    void operator()(FILE* p) const { fclose(p); };
};

using file_handle = std::unique_ptr<FILE, FileHandledeleter>;

int main() { 
    file_handle f { fopen("foo", "w+") };

    auto result = fprintf(f.get(), "Hello");
    if (result < 0) { 
        return -1;
    }

    result = fprintf(f.get(), "World");
    if (result < 0) { 
        return -1;
    }

    return 0;
}

As you can see, a unique_ptr with a custom deleter is used. This deleter will be called when a file_handle object is destroyed and will automatically call fclose.

If you have enough space on your target I would advise on using smart pointers as they facilitate the development and make code less bug prone.

With C++11 being supported by Mbed OS, I think it is worth opening the discussion about there usage in Mbed OS and its examples (might be different answers!).

@donatien Could you share your view ?

1 Like

But are smart pointers fully implemented?

For example, I happed to notice the following compiles for C++ 11 (and up) on my Linux desktop, but I cannot get it to compile in Mbed OS with Arm C6

   #include <memory>
   ...
   std::shared_ptr<int[]> arr = std::shared_ptr<int[]>(new int[20]);
   arr[0] = 0;

Strange there is a difference.

We are using GCC, and we have never used ARM C6, so I cannot say.

It compiles for GCC though, see:

I can switch to GCC, but this then breaks intellisense in Mbed Studio. Also, it’s not an option with Keil Studio I suspect.