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?).
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?
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!).