Static Resource Allocation
What is it?
Static resource allocation is a software design technique in which all memory and resources are reserved at compile-time. No dynamic variables or objects are created while the program runs. Because the memory layout is fixed, the compiler and static analysis tools can verify sizes and addresses, and the system avoids run-time effects such as fragmentation or allocation failure.How it supports functional safety
By eliminating run-time allocation, the technique removes a whole class of systematic failures related to unpredictable memory behavior (e.g., insufficient heap, undetected overlay/overwrite, allocator defects). With a fixed layout, timing remains deterministic and verification becomes simpler. Although it primarily addresses systematic issues, the fixed structure also makes it easier to detect manifestations of random/common-cause hardware faults in memory (e.g., stuck bits) because expected addresses and bounds are known and can be checked.When to use
- Safety functions must meet strict real-time deadlines and worst-case execution time analysis.
- The standard or safety case restricts dynamic allocation (e.g., IEC 61508-3 Tables A.2/B.1; Annex C.2.6.3).
- Independent verification needs a static, auditable memory map and bounded resource usage.
Inputs & Outputs
Inputs
- Hardware memory map (RAM/flash, stack limits, MMU/MPU configuration)
- Worst-case resource demands (buffers, task stacks, queues, tables)
Outputs
- Fixed allocation plan (symbols, sections, linker script)
- Evidence: compiler maps, static-analysis reports, and allocation ban checks
Procedure
- Inventory memory needs: enumerate all buffers, task stacks, message queues, and persistent objects; define credible worst-case sizes.
- Design the layout: assign static storage (globals, static locals, fixed-size pools); define sections in the linker script (e.g., .bss, .data, dedicated IO buffers).
- Ban dynamic allocation: remove/forbid
malloc/calloc/realloc/free,new/delete; configure build rules/LINT to fail on use (including in third-party libraries). - Prove bounds: add compile-time asserts and run-time guards; generate and review the map file; verify each buffer has explicit bounds checks at interfaces.
- Validate timing: measure worst-case execution time with the static layout; confirm no allocation hotspots exist in task paths.
- Document & test: record assumptions, margins, and SAFE REACTIONS for overflow conditions; include unit/integration tests that exercise near-capacity cases.
Worked Example
High-level
A safety PLC regulates a reactor feed valve. Loss or corruption of control data due to heap exhaustion could leave the valve command undefined. By allocating fixed-size input/output buffers and prohibiting dynamic allocation, the control loop always has memory, and any oversize frame is detected and handled safely.Code-level
// Example: static buffers and bounds checks (C-like)
#define RX_FRAME_MAX 64
#define TX_FRAME_MAX 64
static uint8_t rx_frame[RX_FRAME_MAX];
static uint8_t tx_frame[TX_FRAME_MAX];
bool handle_rx(const uint8_t* data, size_t len) {