# Memory Safety & Undefined Behavior Docs: cppreference "Undefined behavior", "Object lifetime", "Smart pointers" (see `cppreference.md`). ## Ownership & lifetime - No owning raw pointers; use `std::unique_ptr` / `std::shared_ptr`, containers, or RAII wrappers. - No `new`/`delete` in application code; use `std::make_unique` / `std::make_shared`. - No references, pointers, `string_view`, or `span` that outlive what they point to (returning views of locals or temporaries, lambdas capturing locals by `&` that escape). - Iterators/pointers/references into containers aren't used after an operation that may invalidate them (`push_back`, `insert`, `erase`, `rehash`). - No use after `std::move` except to reassign or destroy. - Rule of 0/3/5: if a class defines a destructor, copy, or move, it handles all of them correctly (or `= delete`s them). - Base classes used polymorphically have a `virtual` (or protected) destructor. ## Bounds & buffers - Indexing is bounds-checked or provably in range; prefer `.at()` at trust boundaries, `std::span`, range-for. - No `strcpy`, `sprintf`, `gets`, unchecked `memcpy`; sizes come from the destination. - Off-by-one in loop bounds and null terminators. ## Undefined behavior - Signed integer overflow; shifts by negative or >= bit width. - Uninitialized variables (especially scalars and POD members). - Strict aliasing violations; use `std::memcpy` or `std::bit_cast` (C++20) for type punning. - `reinterpret_cast` / C-style casts that change object type; misaligned access. - Null dereference, including `.get()` on empty smart pointers. - Unsequenced modifications (`i = i++`-style). ## C interop - `extern "C"` boundaries: no exceptions propagate into C code. - Memory allocated by C (`malloc`) freed with `free`, not `delete` (and vice versa). - C strings: buffer size and termination checked.