You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(skills): improve spacecraft-cpp-guidelines with Core Guidelines
Enhance the C++ language-guidelines skill by integrating key security checks from the C++ Core Guidelines. Specifically adds rules and skeletons for named lock guards (avoiding immediate destruction races), deadlock-free multi-mutex locking via std::scoped_lock, condition variable predicate checks to prevent spurious wakeups, Rule of Zero & Rule of Five resource management lifecycles, and type-safe scoped enum classes / std::array parameters. Includes recompiled zip and skill packages.
Co-Authored-By: Antigravity (Gemini 3.5 Flash) <noreply@google.com>
-**Stability and Safety first (Standard §3 Priority 1).** C++ historically lacks memory safety. Enforce strict compile-time types using Safe C++ extensions (borrow checker, safe contexts) where available, compile with extensive compiler hardening modes in standard environments, or build with the Fil-C drop-in compiler.
19
19
-**Then Performance (Priority 2).** Do not sacrifice low-latency execution patterns. Utilize zero-overhead compiler hardening options that trap out-of-bounds access with minimal CPU cost.
20
20
-**Modern Concurrency.** Prevent thread leaks and raw thread crashes by using `std::jthread` (C++20+) which provides cooperative thread cancellation tokens and auto-joining destructors.
21
-
-**Deterministic Lifetime Management.** Enforce RAII (Resource Acquisition Is Initialization). Keep allocations bounded, ban raw pointers (`new`/`delete`), and manage resources using smart pointers (`std::unique_ptr`, `std::shared_ptr`).
21
+
-**Deterministic Lifetime Management.** Enforce RAII (Resource Acquisition Is Initialization). Keep allocations bounded, ban raw pointers (`new`/`delete`), and manage resources using smart pointers (`std::unique_ptr`, `std::shared_ptr`). Apply the Rule of Zero (compiler-generated defaults) or Rule of Five (fully handle all copy/move/destructor lifecycle members if one is custom defined).
22
22
23
23
## Memory Safety & Hardening Mode
24
24
-**Safe C++ (safecpp.org) Syntax:** When using Safe C++ compiler extensions (Circle), structure safety-critical paths inside explicit `safe` blocks. Inside `safe {}` contexts, the borrow checker restricts pointer arithmetic, dynamic casting, and raw references, enforcing Rust-like static mutability and lifetime verification.
25
25
-**Compiler Hardening Flags:** In standard C++ toolchains, compiler hardening mode configurations must be active. Trapping bounds errors at runtime is mandatory:
26
26
-**GCC:** Configure `-D_GLIBCXX_ASSERTIONS` and `-fhardened` to trap out-of-bound vector/span access.
27
27
-**Clang:** Configure `-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE` to enable extensive runtime bounds and precondition assertions.
28
28
-**Fil-C Drop-in Safety:** When targeting legacy C++ components, compile code with the Fil-C compiler toolchain fork. Fil-C utilizes garbage collection and InvisiCaps capabilities to trap spatial and temporal access violations, panic-aborting instead of permitting undefined behavior.
29
-
-**Smart Resource Management:** Raw pointer management is prohibited. All dynamic heap allocations must be wrapped in `std::unique_ptr` or `std::shared_ptr`. Avoid `std::shared_ptr` cyclic dependencies.
29
+
-**Smart Resource Management:** Raw pointer management is prohibited. All dynamic heap allocations must be wrapped in `std::unique_ptr` or `std::shared_ptr`. Ownership must never be transferred via raw pointers or references. Prefer `std::array` or `std::vector` over C-style raw arrays, and scoped `enum class` over plain `enum` to prevent implicit casting and namespace pollution.
-**Dynamic Shared Mutation:** Modifying standard containers (e.g., `std::vector`, `std::unordered_map`) across threads without explicit synchronization.
38
38
-**Thread Leakage / Crashes:** Spawning raw `std::thread` elements without joining or detaching before destruction, raising `std::terminate()` crashes.
39
39
-**Contended Mutex Locking:** Performing long-lived blocking mutex locks inside high-frequency real-time loops. Use lock-free structures or fine-grained locks.
40
+
-**Unnamed Lock Guards:** Never declare an unnamed lock guard or unique lock (e.g., `std::lock_guard<std::mutex>(mtx);` is a temporary object that destroys immediately, releasing the mutex instantly and exposing the critical section to data races).
41
+
-**Deadlock Multi-mutex Locking:** Acquiring multiple mutexes individually in different orders. Use `std::scoped_lock` to acquire multiple mutexes atomically and deadlock-free. Never call unknown callbacks or code while holding a lock.
42
+
-**Condition Spurious Wakeups:** Waiting on condition variables without a predicate check, resulting in spurious wakeups and out-of-order execution.
40
43
41
44
## Mandatory Abstraction Choice
42
45
Always choose the safety abstraction corresponding to the compiling environment:
@@ -50,8 +53,10 @@ Always choose the safety abstraction corresponding to the compiling environment:
50
53
1.**jthread over raw thread:** Replace all instances of `std::thread` with `std::jthread`. jthreads auto-join upon exiting their scope and carry interruption tokens.
51
54
2.**Hardened CMake Configuration:** CMake build files must explicitly append GCC/Clang hardening mode compiler flags for compile steps.
52
55
3.**C++26 Span Boundaries:** Use `std::span` to wrap arrays and raw pointers. Hardened runtime flags ensure subscript index queries are trapped upon out-of-bounds attempts.
53
-
4.**RAII Lock Management:** Use `std::lock_guard` or `std::unique_lock` to manage mutex critical sections. Never call `.lock()` and `.unlock()` manually.
56
+
4.**RAII Lock Management:** Use `std::lock_guard` or `std::unique_lock` to manage mutex critical sections, and ensure every lock guard is named. Use `std::scoped_lock` for acquiring multiple mutexes.
54
57
5.**Warnings-as-Errors:** Configure `-Werror` and strict diagnostic flags (`-Wall -Wextra -Wpedantic`) to prevent compilation warnings.
58
+
6.**Rule of Zero/Five:** Enforce the Rule of Zero for resource-free classes, or Rule of Five when manual resource tracking is required.
59
+
7.**Condition variable predicates:** Always invoke condition variable waits using the predicate overload: `cv.wait(lock, [] { return condition; });`.
## 3. Concurrency: Safe Thread Management via `std::jthread`
94
+
## 3. Concurrency: Safe Thread Management, Named Locks, scoped_lock, and Condition Predicates
95
95
96
-
Avoid raw `std::thread` to prevent crashes due to unjoined threads. Use C++20 `std::jthread` to automatically join upon scope exit and handle cooperative thread cancellation.
96
+
Avoid raw `std::thread` to prevent crashes due to unjoined threads. Use C++20 `std::jthread` to automatically join upon scope exit, and always name your lock guards to prevent immediate release vulnerabilities.
97
97
98
98
```cpp
99
99
#include<iostream>
100
100
#include<vector>
101
101
#include<thread>
102
102
#include<mutex>
103
+
#include<condition_variable>
103
104
#include<chrono>
104
105
#include<atomic>
105
106
106
107
classTelemetryWorker {
107
108
private:
108
109
std::mutex mtx_;
110
+
std::condition_variable cv_;
109
111
std::vector<double> readings_;
110
112
std::atomic<bool> status_active_{false};
111
113
std::jthread worker_thread_;
@@ -118,18 +120,21 @@ private:
118
120
// Simulating sensor poll
119
121
double mock_reading = 42.0;
120
122
121
-
// Lock context safely using RAII guard
123
+
// Lock context safely using a NAMED RAII guard
122
124
{
125
+
// CRITICAL: Always name the lock variable (here: 'lock').
126
+
// DO NOT write: std::lock_guard<std::mutex>(mtx_); which creates a temporary that is immediately destroyed!
void transfer_funds(Account& from, Account& to, double amount) {
175
+
// CRITICAL: Use std::scoped_lock to acquire multiple mutexes atomically and deadlock-free
176
+
std::scoped_lock lock(from.mtx_, to.mtx_);
177
+
178
+
from.balance_ -= amount;
179
+
to.balance_ += amount;
180
+
}
157
181
```
158
182
159
183
---
160
184
161
-
## 4. Drop-In Memory Safety: Fil-C Compiler Setup
185
+
## 4. Lifecycle Management: Rule of Zero & Rule of Five
186
+
187
+
If a class does not manage resources directly, rely on the compiler-generated defaults (**Rule of Zero**). If a class manages resources manually, you must explicitly declare or delete all five special member functions (**Rule of Five**).
To run legacy C++ code safely, use the **Fil-C** compiler toolchain. Fil-C replaces raw pointers with capabilities (InvisiCaps) and implements a concurrent garbage collector to block all spatial and temporal bugs.
0 commit comments