Accurately measuring stack usage is essential in safety-critical and embedded software projects. Oversized stacks waste precious memory, while undersized stacks risk catastrophic overflows.
In this post, we’ll explore how you can implement the classic stack painting technique with RapiTest support functions to measure and report task stack usage in your tests.
Why measure stack usage?
In embedded and safety-critical environments, stack allocation is usually static. Each task or function must be given a stack large enough to handle worst-case conditions, but not so large that memory is wasted. Underestimating stack requirements risks stack overflow and unpredictable failures, while overestimating wastes memory resources that are often scarce.
Certification standards such as DO-178C and ISO 26262 require clear evidence that stack sizes are justified and safe. Measuring stack usage is therefore not just good engineering practice, it’s a compliance requirement.
What is stack painting?
Stack painting (or stack watermarking) is a runtime technique for estimating the maximum stack depth a task has reached during execution. It involves the following stages:
- Paint the stack: At initialization, fill the stack memory with a known pattern (e.g.0x99).
- Run the task: As the program executes, stack operations overwrite this pattern.
- Measure usage: After execution, scan the stack from its base until you find the first unmodified pattern. The distance from the base to this point shows how deep the stack grew, the high-water mark.
This method is simple, portable, and widely used in embedded systems. Note that the stack usage observed depends on how well tests execute the code – to observe the absolute worst-case stack usage, a test needs to exist that exercises the code in a sufficient manner.
What are RapiTest support functions?
RapiTest support functions let you write reusable C/C++ logic that can be shared across multiple test cases. Instead of duplicating initialization or measurement code, you can encapsulate it once and invoke it wherever needed.
Typical uses include:
- Test setup and teardown routines
- Complex validation checks
- Mocking and stubbing code
- Custom measurement utilities (like measuring stack usage)
By using support functions for stack painting, you gain both reuse (of the same logic across different tests) and traceability (consistent reporting within RapiTest).
Example implementation
Below is an example implementation of stack painting and measurement using RapiTest support functions:
// ---------------------------------------------------------------------------
// Support functions for measuring maximum stack usage
// ---------------------------------------------------------------------------
static volatile unsigned char *stack_end;
volatile int idx;
/* RVS_ini_stack — Paint the stack with a known pattern.
* @param max Number of bytes to paint downward from the current stack pointer.
*/
void RVS_ini_stack(unsigned int max)
{
volatile unsigned char marker = 0xFF; // Current stack position
stack_end = ▮ // Save stack base
// Fill stack with pattern
for (idx = 0; idx < max; idx++) {
stack_end--; // Move downward (stacks grow down)
*stack_end = 0x99; // Paint memory with known pattern
}
}
/* RVS_measure_stack — Measure maximum stack usage since last initialization.
* @param used Output variable that receives the number of bytes used.
*/
void RVS_measure_stack(unsigned int *used)
{
volatile unsigned char marker = 0xFF; // Current stack position
// Skip untouched bytes
while (*stack_end == 0x99) {stack_end++;}
// Calculate usage
*used = (unsigned int)(&marker - stack_end);
}
Using the stack support functions in a RapiTest test
The example below shows how you might use these support functions in a test case.

This test will:
1. Paint the stack with a pattern.
2. Run the code under test (the LCD task).
3. Measure how much stack space was used.
4. Validate the measured stack usage against the specified threshold.
Reporting results in RapiTest
When you run these tests in RapiTest, the results integrate seamlessly into your usual reports.
In the example below, a test case checks whether stack usage remains under a limit of 256 bytes. RapiTest automatically logs the measured high-water mark (295 bytes in this case) and flags the assertion as failed.

This makes it easy to track stack usage alongside other test results, with clear evidence.
By embedding stack usage checks in your RapiTest campaigns, you can detect potential overflows early and maintain traceable evidence of stack usage behavior throughout your project.
Benefits of this approach
- Reusable: As support functions are encapsulated, you can use them across multiple tests.
- Portable: Works in any C/C++ environment supported by RapiTest.
- Traceable: Stack usage measurements are captured and reported within your RapiTest results.
- Certification-ready: Provides evidence of stack behavior, supporting compliance with safety standards.
- Efficient: Easy to integrate with existing test campaigns.
Conclusion
By implementing ‘stack painting’ via RapiTest support functions, you can efficiently measure stack usage as part of your automated test campaigns.
Want to learn more about how RapiTest can support your software verification projects? You can find out more on our website or sign up to a free trial today.