C++ and Functional Safety (Part I)by Bogdan Andone
In the previous series of posts, we discussed the traction that C has gained in functional safety embedded software over the last thirty years, particularly in regards to the automotive industry.
In this post, we’ll take a look at its challenger: the C++ language.
The history of C++
By this time, C had established a foothold as the natural successor to assembly language, most notably in embedded systems development.
But Stroustrup’s recent experience with the Simula programming language convinced him to develop a superset of C which would bring with it the emerging paradigm of the era: Object Oriented Programming (OOP). Stroustrup had observed the benefits of OOP concepts, but realized that Simula itself was far too slow for deployment in the complex systems addressed by C.
“The class and co-routine mechanisms of Simula and the comprehensive type checking mechanisms ensured that problems and errors did not (as I – and I guess most people – would have expected) grow linearly or more than linearly with the size of the program. Instead, the total program acted more like a collection of small (and therefore easy to write, comprehend, and debug) programs rather than a single large program.”
The new variant was initially titled ‘C with Classes‘. It offered OOP classes and inheritance, and compiled and ran with a similar speed and efficiency to its predecessor.
Four years later a major new version renamed the language ‘C++‘ — a witticism probably lost on anyone except a coder. The name was a wry suggestion that here might be a successor to the now well-established C.
C++ captured commercial and academic interest alike in the 1980s, and consequently was to have a very different development path than its predecessor. By the time of the release of ISO/IEC 9899:1999 in 1999, C had reached a stable maturity which it would maintain in the subsequent two decades.
By contrast, C++ has been perennially driven to adopt new features almost since its inception. The three-year update cycle of C++ routinely introduces new capabilities that are not always backward-compatible. The current iteration dates from only 2017.
Five software programming paradigms in one language
Those who conceived the initial definition of the C language were very inspired. The syntax was flexible enough to allow language extensions, without compromising overall consistency. Bjarne Stroustrup and his collaborators made use of this motility by continuously incorporating into C++ a number of programming concepts that had first emerged in other languages.
C++ natively inherited these two paradigms and added object-oriented programming, the original reason for its creation. It also incorporated generic programming via templates capable of much more powerful functionality than preprocessed macros, and, from C++11 onwards, functional programming.
By supporting all these programming paradigms, C++ facilitates the development of complex software architectures, allowing a better native modularization and isolation of components than C, and encouraging cleaner, more reusable and more maintainable designs. The C++ language definition also includes a standard library of tools (known as the C++ Standard Library), which provides a rich collection of components such as containers, algorithms, mathematical functions, streams and thread management APIs.
Being able to adopt different software development philosophies using just one language is very appealing, but this increased choice brings with it new responsibilities and potential pitfalls.
Of course, different architectural solutions might be more appropriate for deployment under one paradigm than another. However, limiting the number of programming approaches used in a project helps to preserve structural consistency, making the code easier to read and maintain, and avoiding the kind of multi-faceted hybrid codebase illustrated below:
C++ in the automotive industry
C++ is estimated to have over 50% of the market in the automotive software development sector, behind the original C language (at >70%) and well ahead of the venerable Assembly Language and the otherwise unstoppable Python (>25+ and >19%, respectively).
Nonetheless, in spite of its powerful toolset, the automotive development industry is taking a relatively circumspect approach to further adoption of C++, as is evident from the way that the embedded software sector has addressed C++ standardization, historically.
The latest release of the MISRA C standard, which provides development rules for C in state-of-the-art critical systems software, dates from 2012. It’s more recent than the equivalent MISRA C++ standard, which was released in 2008, and covers C++ 03 (2003) – considered by some to be a ‘minor revision’ over its 1998 predecessor. Ten years later, with C++17 full of many new and important features, the Motor Industry Software Reliability Association still shows no visible interest in adoption.
Consequently, the standards bodies seem likely to continue to favor C over C++ as a development standard.
Compromises in the AUTOSAR platform
2003 also saw the establishment of the Automotive Open System Architecture (AUTOSAR) global development partnership. This new alliance between major automotive manufacturers and Tier1 suppliers (including BMW, Siemens, Volkswagen, Bosch, Continental and DaimlerChrysler) sought to establish open industry standards for automotive software architecture and Electronic Control Units (ECUs). It currently has around 100 partners, from OEMs to silicon providers.
AUTOSAR created a scalable layered software architecture with a detailed definition of interfaces for all participating software components. The architecture promotes simplicity and modularity in order to improve design flexibility and to facilitate the reuse of software modules.
Since portability is such a key objective, it is perhaps unsurprising that AUTOSAR initially adopted C as its mandatory software development language.
Though AUTOSAR’s original C-based solutions supported multicore systems and efficient in-vehicle communications on a low-bandwidth vehicle bus such as Controller Area Network (CAN), they were not able to scale over hundreds of cores spread over GPUs and Field Programmable Gate Arrays (FPGAs). Neither could they cope with the volume of traffic generated over Ethernet.
Adaptive and Classic AUTOSAR
This situation led to the emergence of the Adaptive AUTOSAR architecture, designed to address complex automotive systems that cannot be accommodated by the Classic platform, which continues to be used on traditional, deeply-embedded ECUs.
Adaptive AUTOSAR discards much of Classic’s circumscribed strictness. Instead of statically-configured layered architectures that can rely on simple OSEK-like operating systems developed through classical V-cycle processes, the current impetus is around POSIX OS, service-oriented architectures, parallel computing, artificial intelligence and C++; developed, to boot, through agile methodology.
Though it addresses the intervening decade since MISRA C++ 2008, AUTOSAR’s C++14 coding guidelines are far from complete, with further adoption of C++ hampered by the longstanding failure to achieve a library subset that’s officially certified for safety-critical systems.
Without this declaration of limits, and the dedicated investigation necessary to bring it to pass, C++ seems unlikely to deepen its foothold in ECU and similar safety-critical areas of automotive software development.
Additionally, the current guidelines lack concrete solutions to certain practical issues, such as dynamic memory allocation and a number of entry and exit points in functions, instead favoring vague statements of general intent which don’t provide straightforward guidance for developers.
Nonetheless, the current Adaptive AUTOSAR C++14 coding guidelines represent the first real step forward in the adoption of C++ in safety-critical automotive applications.
In a later post, we’ll discuss some of the concrete challenges of building functional safety-critical applications in C++.