2.9 KiB
K03 — FreeRTOS C++ VectorV1: move ownership and RAII
K03 starts from the deliberately incomplete Vector V0: one object owns a
new double[] buffer, but has no destructor and could be shallow-copied. The
card introduces one invariant:
Every live buffer has exactly one owner; a moved-from vector is empty.
The implementation in include/freertos/vector_v1.hpp
adds:
- a destructor that releases the array;
- deleted copy construction and copy assignment;
noexceptmove construction;noexceptmove assignment that first releases the destination's old buffer;- an explicit, testable empty state:
data() == nullptr && size() == 0.
The kernel and heap_4.c remain C. The one C++ linkage unit
src/common/cpp_heap.cpp maps scalar/array and
sized/unsized new/delete to pvPortMalloc() and vPortFree().
One executable, seven checkpoints
task01_vector_raii creates a four-element source and a two-element
destination. Move assignment must release the destination buffer before it
takes the source buffer. A later move construction transfers the same address
again, and the final destructor returns the heap to its baseline.
| Checkpoint | Evidence |
|---|---|
| 1 | initialized heap baseline |
| 2 | source owns buffer A |
| 3 | destination owns buffer B; two live allocations |
| 4 | B released, destination owns A, source empty |
| 5 | final owner owns A, previous destination empty |
| 6 | final owner destroyed; heap already equals baseline |
| 7 | two allocations, two frees, zero live owners, PASS |
Build and verify
The local fallback obtains Hazard3 startup files and simulator from the
neighboring FreeRTOS C scheduler card. A standalone environment can be passed
with RV_ENV_ROOT and TB.
make check
Expected summary:
PASS host: move-only VectorV1, self-move and destructor safety
PASS ABI: no RTTI/vtable/hosted runtime; complete new/delete bridge
PASS task01: Vector V1 move ownership + RAII
The host test uses ASan/UBSan and also proves that a copy attempt fails to
compile. The cross-build is freestanding C++17 with exceptions and RTTI
disabled. Hazard3 runs the real upstream heap_4.c.
Debug
b vector_raii_debug_checkpoint
p g_last_checkpoint
p/x g_source_buffer_before_move
p/x g_destination_old_buffer
p/x g_destination_buffer_after_assignment
p/x g_final_buffer_after_construction
p g_cpp_allocation_count
p g_cpp_deallocation_count
p g_cpp_live_allocations
p g_initial_free
p g_after_two_owners_free
p g_after_scope_free
p g_minimum_ever_free
Scope boundary
This card teaches ownership transfer, not a production container. VectorV1
does not grow, check bounds, select an allocator, or start a task. RAII works
when C++ scopes leave normally; it does not make forced vTaskDelete() or a
system halt unwind arbitrary task-local objects.
Render the printable card with:
make pdf