C++Systems Engineering

Embedded C++ & Safety-Critical Engineering: MISRA, Freestanding, Placement New & std::expected

TT
TopicTrick Team
Embedded C++ & Safety-Critical Engineering: MISRA, Freestanding, Placement New & std::expected

Embedded C++ & Safety-Critical Engineering: MISRA, Freestanding, Placement New & std::expected


Table of Contents


Hosted vs Freestanding C++

mermaid

Why Dynamic Allocation is Forbidden in Safety-Critical Code

In automotive (ISO 26262), aerospace (DO-178C), and medical (IEC 62304) standards, dynamic memory allocation after system initialization is typically prohibited because:

  1. Non-deterministic timing: malloc/new execution time depends on heap state — unpredictable in real-time systems
  2. Fragmentation: Long-running systems with frequent alloc/free develop heap fragmentation — eventual malloc failure
  3. Out-of-memory: Dynamic allocation can fail at runtime; static allocation fails at compile time (link-time)
  4. WCET analysis: Worst-Case Execution Time analysis is impossible when heap allocation time is unbounded
cpp

Static Allocation with Placement New

Placement new constructs an object at a pre-allocated memory location — combining static allocation with C++ object construction:

cpp

No Exceptions: std::expected as Deterministic Error Handling

The -fno-exceptions compiler flag disables C++ exception support entirely — no throw, no try/catch. Use std::expected<T, E> (C++23) for structured error propagation:

cpp

MISRA C++:2023 Key Rules

MISRA C++:2023 (Motor Industry Software Reliability Association) updated for modern C++:

RuleCategoryRationale
No dynamic heap allocation after initRequiredNon-deterministic, fragmentation
No exceptions (-fno-exceptions)RequiredNon-deterministic unwind time
No multiple inheritanceRequiredDiamond problem, layout complexity
No recursion without depth boundRequiredStack overflow risk
override on all overriding functionsRequiredPrevent silent signature mismatch
No gotoRequiredUnstructured control flow
No raw pointer arithmeticAdvisoryBuffer overrun risk
Use RAII for all resourcesRequiredDeterministic release
All variables initialized at declarationRequiredUndefined behavior prevention
No implicit conversions (use static_cast)AdvisoryUnintended narrowing
cpp

Interrupt Service Routines in C++

cpp

Frequently Asked Questions

Is C++ better than C for embedded systems? Yes, when used correctly. C++ templates provide zero-cost abstractions over what C achieves with macros. RAII guarantees register/peripheral cleanup even under error paths. std::array replaces unsafe C arrays. std::expected replaces error-code sprawl. The risk is misusing hosted-only features (std::vector, std::string, exceptions) — MISRA and static analysis tools catch this.

Can I use the STL in embedded code? Selectively. The following are safe in embedded (no dynamic allocation): std::array, std::string_view, std::span, std::optional, std::expected, std::pair/tuple (with trivial types), std::variant, type traits, constexpr algorithms. The following require a heap and are typically forbidden: std::vector, std::string, std::map, std::list, std::function.

What is WCET analysis and how does it affect C++? Worst-Case Execution Time (WCET) analysis determines the maximum time any code path can take — essential for real-time systems where tasks must complete within deadlines. Dynamic dispatch (virtual functions), heap allocation, and exception unwind defeat WCET because their execution time is data-dependent. CRTP (static polymorphism), static allocation, and std::expected are WCET-friendly.


Key Takeaway

Embedded C++ is not "less C++"; it's C++ with explicit constraints turned into engineering discipline. The constraints — no heap after init, no exceptions, deterministic timing — force you to think about resource usage at every level. The reward: code that runs correctly in a car's brake controller for 15 years, a pacemaker's pulse generator for 10 years, or a satellite's attitude control system indefinitely. Mastering these constraints makes you a better engineer for all C++ contexts.

Read next: Enterprise Deployment: CI/CD & Final Wrap-up →


Part of the C++ Mastery Course — 30 modules from modern C++ basics to expert systems engineering.