92 lines
2.9 KiB
Markdown
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
|
|
```
|
|
|