abstract

adesso Blog

Embedded systems are often utilized in safety-critical areas such as aviation, medicine, and automotive technology. The standard IEC 61508-7 provides recommendations for programming languages, which, when using a defined subset, coding guidelines, and static analysis tools, are considered 'particularly recommended' up to SIL4. This includes C and C++. However, the choice of programming language is not self-evident. What factors can influence the decision-making process?

C or C++?

The programming language C has been used in embedded systems for decades due to its direct hardware control and efficient resource utilization. It is ideal for resource-constrained systems and, with its clear language structure, supports deterministic responses and precise control over program flow and resources. However, a disadvantage of C is its low level of abstraction, which can lead to error-prone code. Implicit type conversions and unclear data type definitions can result in unexpected behavior; thus, using C requires a high degree of discipline and care.

The programming language C++ extends C with features such as object-oriented programming, templates, and standard libraries, enhancing code structuring and maintainability. However, the complexity of C++ presents challenges. Performance losses can occur due to mechanisms like exception handling or dynamic memory management. Additionally, unsafe or non-standardized libraries increase the risk of security vulnerabilities.

Standards and Restrictions for Programming Languages, Tools, and Libraries

Numerous tools and best practices can improve the maintainability and quality of C and C++ code in safety-critical systems. These include static analysis tools, unit tests, and code reviews that identify security vulnerabilities, programming errors, and violations of coding standards. Special standards like IEC 61508 or MISRA significantly impact the choice of programming languages, tools, and libraries by imposing specific requirements on development methodology, verification, and validation of software.

Limitations Imposed by Standards

  • IEC 61508 and MISRA: the standards require the use of coding guidelines such as MISRA C or MISRA C++, which govern the use of certain language features. For instance, these guidelines restrict the use of C++ templates, dynamic memory management, and ambiguities in syntax, as these are hard to verify and potentially error-prone. Instead, the use of deterministic and easily understandable constructs is recommended.
  • Tool Qualification: according to IEC 61508, tools used in safety-critical systems must be qualified. This means that the tools must demonstrably not introduce additional risks to software quality. Certified compilers and static analysis tools are particularly helpful in this regard.
  • Model-Based Development: for systems that rely on model-based development, additional requirements exist, e.g., through MISRA AC or specific style guides for automated code generation. These guidelines can apply at both the modeling level and the level of the generated code.

Impacts on the Selection of Tools and Libraries

  • Programming Tools: the choice of suitable development environments and compilers is crucial. Certified compilers that meet the requirements of the standards reduce the risk of unintended side effects. Example: compilers with enabled safety checks or those supporting specific MISRA checks.
  • Libraries: the use of standard libraries (especially in C++) is often restricted, as many functions (e.g., from the Standard Template Library, STL) utilize dynamic memory allocation or other hard-to-control mechanisms. Instead, it is recommended to use libraries specifically developed for safety-critical applications.
  • Code Generation: tools for automatic code generation from models must also meet strict requirements and produce verifiable, compliant results.

Specific Restrictions for C++ Features

  • Templates: while templates in C++ offer a powerful means for generating generic code, they are often restricted in safety-critical applications. The reason lies in the difficulty of fully analyzing and testing the generated code, as well as the potential increase in code complexity.
  • Dynamic Memory Management: C++ features like "new" and "delete" or Smart Pointers are often viewed critically, as they can cause memory leaks or fragmentation. Standards like ISO 26262 recommend using static or stack-based memory instead.
  • Multiple Inheritance: although C++ supports multiple inheritance, it is rarely recommended in safety-critical projects, as it increases code complexity and may introduce potentially hard-to-trace errors.

Interoperability and Runtime Safety in C and C++

The interoperability between C and C++ is relatively straightforward due to the close relationship between the two languages. Existing C modules can be integrated into C++ projects without much effort by embedding the C code in external "C blocks" to avoid name mangling. Conversely, many C++ functions and classes can be used in C, as long as they do not utilize specific C++ features like templates or polymorphic classes. However, care should be taken regarding differences in memory layout and varying compiler implementations to avoid compatibility issues.

Regarding runtime safety, there are significant differences between C and C++. C does not offer built-in mechanisms for error prevention related to runtime errors like null pointer accesses or buffer overflows. Developers must rely on discipline and external tools to avoid such errors. C++ provides more protection against typical runtime errors through advanced language features like exceptions and standard libraries such as std::vector and std::unique_ptr, which reduce the likelihood of memory leaks or undefined behavior. However, the added complexity from C++ features such as templates or dynamic polymorphism can introduce new sources of errors that must be carefully managed, especially in safety-critical applications.

The choice of programming language heavily depends on the specific requirements of the project as well as the expertise of the development team. In many projects, a combination of both languages can present an effective solution. Critical hardware-related functions can be implemented in C to ensure maximum efficiency and control. At the same time, more complex, abstracted modules can be developed in C++ to take advantage of its structuring and maintainability benefits. This hybrid approach, however, requires clear interface definitions and well-documented coding guidelines to ensure smooth integration.

Compliance with standards significantly influences the selection of programming languages, tools, and libraries, imposing clear restrictions on the use of certain language features, particularly in C++.

What criteria do you use to select programming languages in safety-critical applications?

  • IoT & Embedded Systems: innovation for a connected world

    Discover how adesso develops innovative IoT and embedded solutions that help companies digitize and future-proof their products. From concept to implementation, we guide you on the journey to intelligent connectivity. Learn more

  • Embedded C – efficiency and precision in software development

    With Embedded C, adesso delivers customized software solutions for embedded systems that meet the highest standards of efficiency and reliability. Learn how we advance your projects with cutting-edge technologies and proven methodologies. Learn more

  • Functional safety: reliability in safety-critical systems

    adesso supports companies in implementing functional safety for embedded and IoT systems. With extensive expertise, we ensure your products meet the highest safety standards and comply with all regulatory requirements. Learn more

  • Success Story Bühler: digital transformation in the food industry

    Discover how adesso partnered with the Bühler Group to develop innovative digital solutions. Together, we optimized processes and set new benchmarks in the food industry. Learn more

Picture Benno Barten

Author Benno Barten

Benno Barten is a Professional Software Engineer at adesso Schweiz. Throughout his career, he has gained extensive experience in functional safety and the software development of embedded systems, accompanying development from conception to the finished product.