Standard or Third-Party Library – Which One to Trust

In most cases, it is better to use an existing tool than to build your own from scratch. “Don’t reinvent the wheel” is a well-known programming idiom, and libraries are how developers put it into practice. A library is a collection of pre-written code that a developer can include in their project so they don’t have to implement that functionality themselves.

Both C and C++ come with their own “Standard Libraries”. As well as defining the rules of the languages, the ISO standard specifies what the standard library of each must contain.

In addition to the standard library, there are hundreds of third-party C and C++ libraries for various purposes. However, despite how appealing they might look, if the software must meet functional safety standards, it is often wise to avoid using them.

1. Maybe the standard library already has it

Many C++ standard library features originate from popular third-party libraries like Boost, Kokkos, GSL, and fmt. Here are some examples:

C++11

  • std::shared_ptr, std::weak_ptr – Boost.SmartPtr
  • std::function, std::bind – Boost.Function, Boost.Bind
  • std::regex – Boost.Regex
  • std::unordered_map, std::unordered_set – Boost.Unordered

C++17

  • <optional>, <any>, <variant> – Boost
  • <filesystem> – Boost.Filesystem
  • <string_view> – Boost string_ref
  • std::shared_mutex – Boost.Thread

C++20

  • <ranges> – range-v3
  • <format> – fmt
  • <span> – GSL

C++23

  • <expected> – tl::expected, Boost.Outcome
  • <stacktrace> – Boost.Stacktrace
  • <mdspan> – Kokkos

In several of these cases, the proposal to add the feature to the C++ standard was authored by the original library’s maintainer: <ranges> by Eric Niebler, <format> by Victor Zverovich, <stacktrace> by Antony Polukhin.

This list is far from exhaustive, and many more are being added in future versions of C++. So it is quite possible that a feature you need is already in the standard library and just requires an upgrade to a newer version of C++.

2. A third-party dependency can be costly

Adding a dependency on a third-party library is trivial, but maintaining it requires significant effort because it increases your Software Bill of Materials (SBOM). Every third-party library has to be validated against every compiler, compiler version, and platform the project supports. This must be done for each compiler release, which can break code compiled earlier. If the library is eventually removed again, further overhead is added.

Cross-compilation adds more problems. A library written for desktop platforms usually assumes exceptions, RTTI, a heap, and a hosted standard library. On an embedded target, these features may not be available, and the build system itself may not support cross-compilation.

And this is not all: maintainer abandonment, license changes, and CVE (Common Vulnerabilities and Exposures) tracking all become real problems that need to be considered.

3. The “Standard Library” is standard

This means that each language’s standard library is specified in the ISO standard for that language. Most third-party libraries lack this kind of codification. At best, a library might have relatively stable documentation, and some don’t even have that.

Also, the ISO standard specifies constraints that third-party docs usually leave vague: complexity guarantees, exception-safety guarantees, exact iterator-invalidation rules, and thread safety. This makes it possible to derive explicit requirements for each function in the library.

Having a precise specification defined in the ISO document is a major advantage, especially when developing a safety-critical application, where the library is code that goes into the application and must be qualified accordingly. ISO 26262, DO-178C, and IEC 61508 all expect requirements-based testing with traceability for such code. The ISO standard provides a specification against which the library can be qualified.

This qualification, for safety or quality reasons, can be done with Solid Sands’ SuperGuard. It provides requirements and tests that map onto ISO C and C++ library specifications. They can be run against any compiler and target processor, producing the test results and traceability that functional safety standards require.