April 2018: C & C++ Libraries We Like

Welcome to the April 2018 edition of the Embedded Artistry Newsletter! This is a monthly newsletter of curated and original content to help you build better embedded systems. This newsletter is intended to supplement the website and covers topics not mentioned there.

This month we'll cover:

  • Seven exceptional C and C++ projects to consider for your next product
  • Interesting links from around the web
  • Embedded Artistry website updates and popular posts

Open Source Projects to Consider For Your Next Product

I’ve selected seven exceptional C & C++ projects that I want to share with you. Integrating high-quality libraries in our code base enables us to take new approaches, use safer techniques, or simply reduces the amount of code we need to write. I hate reinventing the wheel unless there’s a compelling reason, so I like to spend time researching libraries before diving into development. I hope you can find something to benefit your next product.

C++ Projects

I primarily focus on developing new embedded systems in C++. The language provides features that allow me to write safer code and to detect errors in compilation rather than at runtime. Of the seven project we’ll review today, 5 of them are C++:

  • NamedType
  • foonathan/type_safe
  • foonathan/memory
  • POCO C++ Libraries
  • Safer C++

NamedType

NamedType is a library written by Jonathan Boccara, a C++ developer and author of the FluentC++ blog. The NamedType library provides a simple interface for using strong types, which are not natively supported in C++.

We often utilize native types, such as int or double, to represent the values in our software. The general nature of these types means that we can easily make mistakes in our code. Consider a simple rectangle constructor:

Rectangle(double width, double height);

If you swapped the width or height in your code, the compiler would never be able to tell you.

double width = 10.5;
double height = 3.0;
Rectangle r(height, width); // wrong but compiles!

By using strong types in our interfaces, we can make our APIs more explicit and rely on the compiler to catch any mistakes:

// Create our strong types
using Width = NamedType<double, struct WidthTag>;
using Height = NamedType<double, struct HeightTag>;
//…
Rectangle(Width width, Height height); // new constructor
//…
Rectangle r(Height(3.0), Width(10.5)); // compiler error - type mismatch!
Rectangle r2(Width(10.5), Height(3.0)); // ok

The great news is that strong types are zero-cost when compiling with -O2 (or -O1 with GCC). It's time to make your APIs more explicit and catch errors during compilation.

For more on NamedType and strong types in C++:

type_safe

The type_safe library is developed by Jonathan Müller, a C++ library and author of foonathan::blog(). The type_safe library provides zero-overhead utilities to help catch bugs at compile time.

Features provided by the type_safe library include improved built-in types (ts::integer, ts::floating_point, and ts::boolean) which prevent dangerous implicit operations like signed-to-unsigned promotion. The type-safe library also provides "vocabulary" types to help us write more expressive code, such as object_ref (non-null ptr), array_ref (reference to an array), and function_ref (reference to a function). Other interesting concepts are also provided, such as deferred_construction, a wrapper which allows you to create an object without constructing.

Similar to NamedType, this library also supports strong types. Where NamedType provides a simple interface for creating strong types, the type_safe library requires explicit declaration of the attributes our strong type supports. The increased overhead for setting up new types is worth the safety provided by explicitly deciding what operations should be allowed. In the example below, our strong type only has addition and subtraction operations enabled:

struct meter
: strong_typedef<meter, int>, addition<meter>, subtraction<meter>
{
    using strong_typedef::strong_typedef;
};

Use the type_safe library to write expressive code and increase the number of errors caught during compilation.

For more on type_safe:

memory

The memory library is also developed by Jonathan Müller. This library provides an new STL-compatible C+ memory allocator called RawAllocator. The RawAllocator is similar to the standard Allocator but is easier to use. The library also provides a BlockAllocator type which can be used for allocating large blocks of memory.

The project includes a variety of implementations, adapters, wrappers, and storage classes, including:

  • new allocator
  • heap allocator
  • malloc allocator
  • memory pools
  • static allocator
  • virtual memory allocator
  • make_unique and make_shared replacements which allocate memory using a RawAllocator

We are excited about using this library in our next embedded project and gaining increased control over memory allocations.

For more on the memory library:

POCO C++ Libraries

The POrtable COmponents (POCO) C++ Libraries is a collection of C++ class libraries whose goal is to simplify the development of network-centric applications. POCO is similar in concept to the Java Class Library, .NET Framework, or Cocoa. The POCO libraries are highly portable, allowing you to easily compile and run your application on multiple platforms.

The full list of features provided by the POCO libraries are too numerous to list here. A small sampling of features:

  • Caching framework
  • Cryptographic & hashing libraries
  • Logging framework
  • HTTP server & client
  • SSL/TLS support through OpenSSL
  • POP3 & SMTP clients
  • SQL database access
  • Multithreading (basic threads, synchronization, thread pools, active objects, work queues)
  • Stream classes for Base64 and binary encoding/decoding, compression (zlib), line ending conversion
  • XML parsing & generation
  • Zip file manipulation

While the POCO libraries provide portability and a plethora of features, my favorite aspect is the emphasis on code quality, style, consistency, and readability.

I highly recommend reviewing the POCO libraries before beginning your next project - you can find a gem (or twenty) that will save you development time.

For more on POCO:

SaferC++

The SaferC++ library provides safer implementations for many native C++ types. The library provides features such as:

  • Data types that are designed for multi-threaded use and asynchronous access
  • Drop-in replacements for std::vector, std::array, std::string, std::string_view that provide improved memory safety
  • Drop-in replacements for int, size_t, and bool that protect against use of uninitialized values and sign-unsigned comparison issues (similar to type_safe)
  • Improved pointer & reference types with different compatibility and performance tradeoffs

SaferC++ is usable with embedded systems as long as your platform has a functional STL implementation. Exception behavior can be controlled for your platform by modifying the MSE_CUSTOM_THROW_DEFINITION macro.

Using the library does incur a performance penalty. However, SaferC++ elements can be disabled during compile time (i.e. replaced with the standard type equivalents). This allows users to enable debug and test builds to use safer-but-slower features without adding overhead to release builds.

Since the SaferC++ types provide added safety and can be disabled when performance matters, I highly recommend using their drop-in types to catch and eliminate possible errors when using STL types. The easiest way to get started with SaferC++ is to utilize the mse::vector and mse::array types in place of std::vector and std::array. These types will help you catch potential memory issues lurking in your software. The README provides further tips for making your code safer.

For more on SaferC++:

C Projects

While we’ve been heavily focused on C++-based embedded systems development for the past few years, I did find two exciting C projects that I want to share with you:

  1. CException, a lightweight exception library
  2. Checked C, an extension to the C language which provides better protections against common memory errors

CException

CException is a project released by Throw The Switch. CException is designed to provide simple exception handling in C using the familiar try/catch/throw syntax. I've been recently thinking about the downsides of error logging, so I am excited to see a lightweight exception library for C.

The exception implementation is kept simple by only allowing you to throw a single error code. No support for throwing objects, structs, or strings is included. The library can be configured for either single-tasking or multi-tasking which makes this project a good fit for embedded systems using an RTOS. CException is implemented in ANSI C and is highly portable. As long as your system supports the standard library calls setjmp and longjmp, you can use CException in your project. If you're looking for an exception library to use on embedded systems, CException is for you.

For more on CException:

Checked C

Checked C is a research project from Microsoft which adds static and dynamic (runtime) checking for errors such as buffer overruns, out-of-bounds memory accesses, and incorrect type casts.

The project is implemented as an extension to the C language. New pointer and array types are provided with the goal of allowing programmers to better describe intended pointer use and the range of memory that is pointed to. Developers can select between types with and without bounds checking, as well as between types that can or cannot be used in pointer arithmetic.

Since Checked C is an extension to the C language, you will need a compiler that supports it. Microsoft provides a port of clang and LLVM that support the extension.

CheckedC can help you identify and eliminate common memory errors which plague us as C & C++ developers. Even better, existing C programs compiled with a Checked C compiler will continue to work. Raw pointers (e.g. int *) remain unchecked and pointer arithmetic is still allowed.

For more on Checked C:

Around the Web

In the September 2017 newsletter I shared a series of posts detailing the engineering behind the Voyager missions. If you liked those articles, Voyager Mission Telecommunication Firsts presents another take on the outstanding engineering achievements of the Voyager missions.

If you enjoyed last month's focus on development processes, I recommend reading Making Valgrind Easy. By integrating Valgrind into your static analysis process, you can find and fix memory issues that your compiler or static analyzer won't catch.

I came across this article written by Michael Barr in 2009, titled Firmware Architecture in Five Easy Steps. Read this article before starting your next embedded project.

Jonathan Müller of foonathan posted Guidelines for Rvalue References in APIs. This article is recommended for advanced C++ developers and library authors.

Website Updates

Our "About" information has been condensed into a single page. We've doubled down on keeping the primary website focused on embedded systems content. We've created a new website dedicated to our consulting business.

A classic (and free!) introductory embedded systems book, Programming Embedded Systems, was added to the Beginners page. While the examples are slightly dated, the concepts are valid and can be applied to modern embedded systems.

The Glossary saw new additions, including LVDS, PLM, and MIPI standards.

The old "Open Source Software" page has been merged into the Libraries page.

New Articles

The Dark Side of Error Logging was published as a guest post on Arne Mertz's Simplify C++ blog.

These posts were published on our website in March:

  1. Improving Our Software With 5 Lightweight Processes You Can Adopt This Month
  2. Getting Started with the Snapdragon Flight: Driver Development
  3. Seeing Intermittent GitHub Clone Failures on Jenkins? Check Your Repo Size
  4. Safely Storing Secrets in git

These were the most popular articles in March:

  1. Circular Buffers in C/C++
  2. C++ Casting, or: Oh No, They Broke Malloc!"
  3. Installing LLVM/Clang on OSX
  4. std::string vs C-strings
  5. Jenkins: Configuring a Linux Slave Node
  6. An Overview of C++ STL Containers
  7. Implementing Malloc: First-fit Free List
  8. Demystifying ARM Floating Point Compiler Options
  9. Jenkins: Running Steps as sudo
  10. Creating and Enforcing a Code Formatting Standard with clang-format

Thanks for Reading!

Have any feedback, questions, suggestions, interesting articles, or resources to recommend to other developers? Simply reply to this email!

While you wait on the next edition, check out the website or follow us on Twitter

Happy hacking!

-Phillip