Programming, Code quality, Debugging, Embedded DevOps

Enabling memory-safe C/C++ development without a language shift

<span id="hs_cos_wrapper_name" class="hs_cos_wrapper hs_cos_wrapper_meta_field hs_cos_wrapper_type_text" style="" data-hs-cos-general-type="meta_field" data-hs-cos-type="text" >Enabling memory-safe C/C++ development without a language shift</span>

Lately, there has been a lot of discussion in the industry about the value of memory-safe languages and development in the embedded space, particularly as it applies to the security and safety of products. 

Lack of memory safety is a key mechanism for introducing security vulnerabilities into products, risking both their safety and security. 

As someone who has worked alongside many embedded teams over the years, I’ve seen firsthand how these challenges show up in real projects. That’s why I wanted to share how the IAR platform can help solve this specifically using its built-in runtime code checker that uncovers memory safety issues in C and C++ code, making these traditionally non-memory-safe languages much safer to work with. 

What is memory safety? 

Memory safety typically falls into two categories: 

  • Spatial memory safety:  Can you create an operation that reads or writes memory spaces it should not touch? 
  • Temporal memory safety: Does the temporary use of memory affect overall memory management in unsafe ways? 

In the C language, the first issue can occur by declaring an array of a certain size and then accessing elements outside the bounds of the array, something that is completely legal in C and C++. 

The second issue refers to heap memory allocation, typically done using malloc() and free() paired calls. If too many malloc() calls are made without freeing the blocks allocated, you can easily create situations where memory leaks occur, or worse, where accesses beyond the heap overwrite other memory such as global variables. 

While C++ offers more automatic handling in some cases, it is still entirely possible to manually allocate memory, exposing the same kind of risk. 

How can I check for this behavior? 

This is where the IAR Embedded Workbench and the broader IAR platform come into play. 

IAR provides a runtime code checker called C-RUN. 
This tool checks for several dangerous behaviors, including trapping memory array out-of-bounds operations as well as heap overflows, making it an ideal solution to help make your C or C++ code memory safe during live debug. 

C-RUN’s setup screen shows the different checks it can perform in a live debug session, all set up within a single interface, part of the fully integrated IAR platform experience. 

C-RUN picture 1

This graphic shows the setup of C-RUN from the project options with all options enabled. 
Highlighted boxes indicate that C-RUN is active, and both heap usage as well as array bounds checking are turned on. 
This setup provides live checking of the two most common sources of memory safety errors in C and C++ code. 

In addition, C-RUN can check for arithmetic error conditions on the right side of the setup window. While these checks are also useful for validating code integrity, I will not cover them in this discussion. 

Live Debug results 

When running inside the IAR C-SPY debugger, C-RUN-instrumented code can catch both memory leak conditions and array out-of-bounds accesses before they execute and have the chance to affect system behavior.  

C-RUN picture 2

For example, a program might create an array with 100 values, where each element is pre-loaded with its index value. 
In this case, the Terminal I/O window instructs the user to enter a value less than 100 to use as an array index. 

If the user enters the value 102, the program will attempt to access the array outside its defined bounds. 
When this happens, the debugger halts execution at the offending line before the operation is carried out and displays detailed messages in the C-RUN Messages window explaining what it has found.  

C-RUN picture 3a

Specifically, the debugger stops at the line of code about to perform the out-of-bounds array access to element 102 of an array that only holds elements 0–99. 

C-RUN picture 3b

In the C-RUN Messages window, it explicitly indicates that the error occurred on line 21 in the main.c source file and points back to the array declaration on line 8.  

C-RUN picture 4

If the code were allowed to continue, the system might not immediately crash, but the array at index 102 would return the invalid value 134229899,  clearly incorrect. 

 C-RUN picture 5

Additionally, C-RUN reports on heap allocations. For example, if heap space is set to 0x2000 bytes and a loop allocates 0x800 bytes with each malloc() call, C-RUN will trap the fourth malloc() operation after 6228 bytes have been allocated, preventing the heap from overflowing. 
By doing so, it avoids unsafe behavior where a memory block might return a pointer that accesses non-heap memory. 

 From live debugging to automation: Scaling memory-safe checks 

While live debugging with C-RUN is incredibly effective at catching errors during development, today’s fast-paced embedded projects demand more. Teams are no longer dealing with just one product variant or one test setup, they are juggling multiple software versions, hardware configurations, and release branches, all under tight deadlines. 

This is where automation becomes essential. 

Manually checking memory safety on every build and every target is no longer scalable. To meet the demands of continuous delivery, teams need to automate memory safety checks as part of their CI/CD workflows and this is exactly where C-RUN shows its full potential. 

Automation-ready for CI/CD workflows with C-RUN 

Modern embedded development is no longer just about manual debugging sessions. To keep up with fast-moving release cycles and ensure product quality at scale, teams need automation and C-RUN is built for it. 

C-RUN integrates seamlessly into automated testing pipelines by running within the IAR C-SPY Debugger in batch mode. 
This allows you to: 

  • Apply predefined rules and settings automatically across builds 
  • Redirect output to log files or external reporting tools for centralized tracking 
  • Incorporate memory safety checks directly into continuous integration (CI) pipelines 

 C-RUN picture 6

By doing so, C-RUN supports scalable testing, ensuring that every software change, across every version, or configuration, is validated for memory safety before it reaches production. 

What’s stopping your team from making C and C++ safer today? 

This example shows how the C-RUN runtime code checker, delivered as part of the complete IAR platform, can effectively clean C and C++ code of unsafe memory operations. 

By using this integrated approach, teams can eliminate the need to move to a “memory-safe” language that might introduce other challenges or disrupt existing development cycles. 

C-RUN has been part of the IAR toolchain for well over a decade and remains a proven, reliable way to help teams produce memory-safe code using the familiar C and C++ environments they rely on. 

For embedded developers, it’s not just about having individual tools, it’s about having a comprehensive platform that brings everything together to improve safety, security, and code quality from the developer’s workstation all the way to automated CI/CD pipelines, across the entire development process.  

Ready to tackle memory safety in C/C++? 

If memory issues like buffer overflows or heap misuse are slowing your team down—or worse, introducing safety and security risks—you're not alone, and you don’t need to switch languages to solve the problem. 

Want to see it in action? Watch our on-demand webinar, Surviving without a DevOps team: CI/CD, debugging, and containers for embedded teams to learn how runtime checks, automation, and modern workflows can help even small teams deliver safer embedded software. 

Looking for a scalable DevSecOps approach? Check out Breaking the CI/CD bottleneck: Scaling embedded DevSecOps with containers & automation to see how to integrate C-RUN into your automated testing workflows.