Files

92 lines
2.9 KiB
Markdown

# 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`](include/freertos/vector_v1.hpp)
adds:
- a destructor that releases the array;
- deleted copy construction and copy assignment;
- `noexcept` move construction;
- `noexcept` move 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`](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`.
```sh
make check
```
Expected summary:
```text
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
```gdb
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:
```sh
make pdf
```