Skip to content
Back to skills

Cpp

ASecurity

C and C++ stack guide - modern target-based CMake and presets, vcpkg/Conan, compiler warnings, RAII, smart pointers, rule of zero/five, move semantics, undefined behaviour, ASan/UBSan/TSan, clang-tidy, GoogleTest/Catch2, fuzzing, memory-safety pitfalls, perf profiling, linker error playbook. Use for any C/C++ code, CMakeLists.txt or build/link failure. Триггеры - "плюсы", "си", "не линкуется".

  • 2 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 13, 2026
ai-agentsrustgoc++shellnodetestinggitapisecurityperformance

Works with

  • api
  • mcp

Security analysis

A100/100

Pro scans all 6 files and shows the line behind each finding

Scanned October 13, 2026

npx -y skills add dmminga1983/minga --skill cpp --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Cpp?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Cpp
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/dmminga1983-cpp/badge)](https://www.skillsdirectory.com/skills/dmminga1983-cpp)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: cpp
description: C and C++ stack guide - modern target-based CMake and presets, vcpkg/Conan, compiler warnings, RAII, smart pointers, rule of zero/five, move semantics, undefined behaviour, ASan/UBSan/TSan, clang-tidy, GoogleTest/Catch2, fuzzing, memory-safety pitfalls, perf profiling, linker error playbook. Use for any C/C++ code, CMakeLists.txt or build/link failure. Триггеры - "плюсы", "си", "не линкуется".
paths: "**/*.c, **/*.h, **/*.cc, **/*.cpp, **/*.cxx, **/*.hpp, **/*.hh, **/*.hxx, **/*.ipp, **/*.inl, **/CMakeLists.txt, **/*.cmake, CMakePresets.json, vcpkg.json, conanfile.txt, conanfile.py, meson.build, .clang-tidy, .clang-format"
---

Reply in the user's language.

# C and C++

Rule zero: **follow the project's existing conventions over these defaults.** Read before you write.

## 1. Detect the project

| Read | To learn |
|---|---|
| `CMakeLists.txt` (root and subdirs), `cmake/*.cmake` | CMake minimum version, targets, language standard, options, how dependencies are found |
| `CMakePresets.json` / `CMakeUserPresets.json` | named configure/build/test presets — use them instead of inventing flags |
| `vcpkg.json` (+ `vcpkg-configuration.json`) | vcpkg manifest mode, baseline, features |
| `conanfile.txt` / `conanfile.py`, Conan profiles | Conan dependencies and settings |
| `meson.build`, `Makefile`, `configure.ac`, `MODULE.bazel`/`BUILD`, `*.vcxproj` | other build systems — use them as they are; don't migrate unasked |
| `.clang-format`, `.clang-tidy`, `.editorconfig`, `compile_commands.json` | style, enabled checks, the real compile flags |
| CI files | compilers and versions, standard, sanitizer jobs, warning policy |
| headers style | C or C++, standard (`std::span`, concepts, `<format>` suggest C++20), exceptions/RTTI allowed?, naming |

Ask, or check CI, for the supported compilers (GCC, Clang, MSVC, Apple Clang) and platforms; portability limits what you may use.

## 2. Defaults for new code

- **Standard:** C++20 (or what the project uses) via `target_compile_features(<t> PUBLIC cxx_std_20)`; C17 for C (`c_std_17`). No compiler-specific extensions unless the project relies on them (`CMAKE_CXX_EXTENSIONS OFF`).
- **Build:** out-of-source, `cmake -S . -B build` then `cmake --build build`, or `cmake --preset <name>` + `cmake --build --preset <name>`. Personal presets go in `CMakeUserPresets.json` (git-ignored).
- **Modern CMake:** everything is a target; per-target `target_include_directories`, `target_link_libraries`, `target_compile_options`, `target_compile_definitions` with `PUBLIC`/`PRIVATE`/`INTERFACE`. No global `include_directories`, `link_libraries`, `add_definitions` or editing `CMAKE_CXX_FLAGS` in project files. Details: [cmake.md](cmake.md).
- **Dependencies:** the project's package manager (vcpkg manifest, Conan 2, or `FetchContent` for small header/source deps) consumed via `find_package(... CONFIG REQUIRED)` and imported targets (`fmt::fmt`).
- **Warnings:** GCC/Clang `-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wsign-conversion -Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual -Wformat=2 -Wimplicit-fallthrough`; MSVC `/W4 /permissive-`. Warnings as errors in CI (`CMAKE_COMPILE_WARNING_AS_ERROR` or `-Werror` in a preset), not forced on consumers of a library.
- **Tooling:** `CMAKE_EXPORT_COMPILE_COMMANDS=ON` for clangd/clang-tidy; clang-format for formatting.
- **Libraries:** `fmt`/`std::format`, `spdlog` for logging, GoogleTest or Catch2 for tests — only if the project doesn't already have equivalents.

## 3. Idioms and design (C++)

1. **RAII for every resource** (memory, files, sockets, locks, handles). No naked `new`/`delete`; wrap C handles in `std::unique_ptr<T, Deleter>` or a small owning class.
2. **Ownership in types:** `std::unique_ptr` = sole owner (default), `std::shared_ptr` = genuinely shared (rare; beware cycles → `std::weak_ptr`), raw pointer / reference = non-owning observer. Create with `std::make_unique` / `std::make_shared`.
3. **Rule of zero:** let members manage resources so the class needs no destructor/copy/move. If you write any of destructor, copy ctor/assignment, move ctor/assignment, think about all five (**rule of five**), and `= default` / `= delete` explicitly.
4. **Move semantics:** moved-from objects are valid but unspecified — don't use them except to assign or destroy. Mark move constructors `noexcept` (containers fall back to copying otherwise). Don't `std::move` a return of a local (blocks copy elision), and never `std::move` from a `const` object.
5. **Parameters:** cheap types by value; read-only large types by `const T&` or `std::string_view` / `std::span<const T>`; sink parameters by value then `std::move`. Never store a `string_view`/`span` that outlives its source.
6. **const-correctness:** `const` member functions, `const` locals by default, `constexpr` where possible; `[[nodiscard]]` on functions whose result must be used.
7. **Polymorphic bases:** public virtual destructor (or protected non-virtual); `override` on overrides, `final` where intended; no virtual calls in constructors/destructors.
8. **Explicit:** single-argument constructors `explicit`; `enum class` over plain enums; `static_cast` etc. over C casts; `nullptr` not `NULL`/`0`.
9. **Containers and algorithms:** `std::vector` by default; `<algorithm>`/ranges over hand-written loops; `.at()` or checked access at trust boundaries; watch iterator/reference invalidation after `push_back`, `insert`, `erase`.
10. **Error strategy is a project decision:** exceptions, `std::expected` (C++23)/`tl::expected`, or error codes — be consistent. Destructors and move operations don't throw.
11. **Headers:** include what you use; include guards or `#pragma once`; no `using namespace` in headers; keep headers light (forward declarations, pimpl for ABI-stable libraries).
12. **Concurrency:** `std::jthread`/`std::thread` joined, `std::scoped_lock` for multiple mutexes, `std::atomic` for simple flags/counters; shared mutable data is either guarded or immutable. Data races are UB.
13. **C code:** check every return value; one clear owner per allocation, freed on all paths (`goto cleanup` is idiomatic); sizes in `size_t`; bounds passed alongside pointers; `static` for file-local functions; no VLAs from untrusted sizes.

Undefined behaviour you must not rely on, with examples: [undefined-behaviour.md](undefined-behaviour.md).

## 4. Errors and logging

- Don't ignore errors: `[[nodiscard]]` on error-returning functions; check `errno`-based APIs immediately; convert C error codes into the project's error type at the boundary.
- Exceptions: throw by value, catch by `const&`; derive from `std::exception`; catch at boundaries (thread entry, `main`, API surface). Never let exceptions escape destructors, `noexcept` functions, C callbacks or across a C ABI.
- `assert` for internal invariants (disabled with `NDEBUG`); real validation for external input regardless of build type.
- Logging: the project's logger (spdlog, glog, custom); format with `fmt`/`std::format` — never pass user data as a format string. Don't log secrets or full buffers.

## 5. Testing

- **GoogleTest:** `TEST(Suite, Case)`, fixtures with `TEST_F`, `EXPECT_*` (continues) vs `ASSERT_*` (stops), parameterised `TEST_P`; register with `include(GoogleTest)` + `gtest_discover_tests(<target>)`; link `GTest::gtest_main`.
- **Catch2 (v3):** `TEST_CASE("name", "[tag]")`, `SECTION`, `REQUIRE`/`CHECK`, generators; link `Catch2::Catch2WithMain`, register with `catch_discover_tests`.
- **Layout:** `tests/` with its own `CMakeLists.txt`, guarded by an option or `BUILD_TESTING` (`include(CTest)`); the library is a target the test links against — don't recompile sources into the test.
- **Commands:**
  - all: `ctest --test-dir build --output-on-failure` (or `ctest --preset <name>`)
  - by name: `ctest --test-dir build -R 'Parser'`
  - GoogleTest directly: `./build/tests/unit_tests --gtest_filter='Parser.*'`
  - Catch2 directly: `./build/tests/unit_tests "[parser]"`
- **Sanitizers in tests:** a dedicated preset/build with `-fsanitize=address,undefined -fno-omit-frame-pointer -g` (Clang/GCC); TSan in a separate build (`-fsanitize=thread`, cannot be combined with ASan); MSVC supports `/fsanitize=address`. Make UBSan fatal with `-fno-sanitize-recover=undefined`.
- **Fuzzing:** libFuzzer target `extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)` built with `-fsanitize=fuzzer,address` (Clang), or AFL++. Fuzz every parser of untrusted input; keep crashing inputs as regression tests.
- **Coverage:** `--coverage` (gcov/lcov/gcovr) or Clang source-based coverage (`-fprofile-instr-generate -fcoverage-mapping`, `llvm-cov`).
- **Static analysis:** `clang-tidy -p build <file>` (or `run-clang-tidy -p build`), driven by `.clang-tidy` (common sets: `bugprone-*`, `cert-*`, `cppcoreguidelines-*`, `modernize-*`, `performance-*`); `cppcheck`; compiler `-fanalyzer` (GCC) where useful.

## 6. Security pitfalls

- **Buffer overflows:** no `gets`, `strcpy`, `strcat`, `sprintf`, `scanf("%s")`, unchecked `memcpy`. Use `std::string`, `std::vector`, `std::span` with sizes, `snprintf` (check its return for truncation), `std::format`. Every pointer + length pair is validated before use.
- **Format strings:** `printf(user_input)` is an exploit — always `printf("%s", s)`; enable `-Wformat=2 -Wformat-security`; `fmt`/`std::format` check format strings at compile time.
- **Integer overflow:** size computations (`count * sizeof(T)`, `a + b` before allocation) must be checked (`__builtin_mul_overflow`, C23 `ckd_mul`, or explicit limits); signed overflow is UB; mixing signed/unsigned in comparisons (`-Wsign-compare`, `-Wsign-conversion`). `std::atoi` has no error reporting — use `std::from_chars` or `strtol` with checks.
- **Memory lifetime:** use-after-free, double free, dangling references/views/iterators — prevented by RAII and ownership types, detected by ASan.
- **Unsafe C APIs:** `system`/`popen` with user data (shell injection — use `execve`-family with argument arrays); `rand()` for secrets (use the OS CSPRNG: `getrandom`, `BCryptGenRandom`, or a vetted library); `tmpnam`/`mktemp` (use `mkstemp`); TOCTOU between `access()` and `open()`.
- **Secrets in memory:** wipe with `explicit_bzero` / `memset_s` / `SecureZeroMemory` — plain `memset` before free may be optimised away.
- **Hardening** (release builds, where supported): `-D_FORTIFY_SOURCE=2` or `3` (needs optimisation), `-fstack-protector-strong`, `-fstack-clash-protection`, PIE, full RELRO (`-Wl,-z,relro,-z,now`), `-D_GLIBCXX_ASSERTIONS` or libc++ hardening mode in debug/test builds; MSVC `/GS`, `/guard:cf`, `/sdl`.
- **Dependencies:** pin versions via vcpkg baseline or Conan lockfiles; track advisories for vendored code (zlib, OpenSSL, libpng, etc.); don't copy-paste third-party code without its licence and an update path.

Full UB catalogue and checks: [undefined-behaviour.md](undefined-behaviour.md).

## 7. Performance pitfalls

- **Measure on optimised builds with symbols:** `RelWithDebInfo` (or `-O2 -g -fno-omit-frame-pointer`). Linux: `perf stat ./app`, `perf record -g ./app` then `perf report`; flame graphs from `perf script`. Also `valgrind --tool=callgrind`, `heaptrack`, VTune, Instruments, Visual Studio profiler. Micro-benchmarks with Google Benchmark (`benchmark::DoNotOptimize`).
- **Cache-friendly data:** contiguous containers (`std::vector`, flat maps) over node-based (`std::list`, `std::map`) in hot paths; struct-of-arrays for hot fields; avoid pointer chasing; keep hot data small; avoid false sharing between threads (pad or separate per-thread counters).
- **Allocations:** `reserve()` known sizes; reuse buffers; avoid `std::shared_ptr` churn (atomic refcounts); `std::string_view` to avoid copies; small-buffer-friendly types.
- **Copies:** pass large objects by `const&`; move into sinks; `emplace_back` for in-place construction; return by value (RVO).
- **I/O:** `'\n'` instead of `std::endl` (flushes); buffered writes; `std::ios::sync_with_stdio(false)` in iostream-heavy tools.
- **Dispatch:** virtual calls or `std::function` in tight loops block inlining; templates/CRTP or batching help.
- **Build-level:** LTO (`CMAKE_INTERPROCEDURAL_OPTIMIZATION`), PGO for hot binaries; `-march=native` only for binaries that run on the build machine.

## 8. Build and link errors

Read the **first** error; for template walls find the first `error:` and the `required from here` line in your code. Full playbook: [build-errors.md](build-errors.md).

| Symptom | Likely cause | Fix |
|---|---|---|
| `undefined reference to 'foo'` / MSVC LNK2019 unresolved external symbol | source not in the target, library not linked, C/C++ mangling mismatch, template defined in `.cpp`, static library order | add the source / `target_link_libraries`; `extern "C"` in C headers; templates in headers; let CMake order libraries |
| `undefined reference to 'vtable for X'` | first non-inline virtual function (often the destructor) declared but never defined | define it (or `= default` in the `.cpp`) |
| `multiple definition of 'foo'` / LNK2005 | non-inline function or global variable defined in a header | mark `inline` (C++17 inline variables), or declare `extern` in the header and define once |
| `fatal error: foo.h: No such file or directory` | include path missing or dependency not linked as a target | `target_link_libraries` to the imported target (carries include dirs); install the `-dev` package |
| `Could not find a package configuration file provided by "Foo"` | package not installed, or vcpkg/Conan toolchain not passed | install it; pass the toolchain file at first configure; set `CMAKE_PREFIX_PATH` |
| undefined `std::__cxx11::basic_string` symbols | libstdc++ dual ABI mismatch between your code and a prebuilt library | rebuild the library with the same compiler/`_GLIBCXX_USE_CXX11_ABI` setting |
| LNK2038 mismatch detected for 'RuntimeLibrary' / '_ITERATOR_DEBUG_LEVEL' | mixing `/MD` and `/MT`, or Debug and Release libraries | build everything with the same runtime (`CMAKE_MSVC_RUNTIME_LIBRARY`) and configuration |
| `relocation R_X86_64_32 ... recompile with -fPIC` | static code linked into a shared library | `set(CMAKE_POSITION_INDEPENDENT_CODE ON)` or the target property |
| `error while loading shared libraries: libfoo.so` | runtime loader can't find the library | install it, set RPATH (CMake install RPATH settings), or `LD_LIBRARY_PATH` for local runs |
| strange crashes, different behaviour per TU | ODR violation (two definitions differ: macros, flags, struct layout) | one definition per entity; same defines/flags everywhere; GCC `-Wodr` with LTO, ASan ODR detection |
| `use of deleted function` (copy of `unique_ptr`, mutex) | copying a move-only type | `std::move`, pass by reference, or redesign ownership |
| `invalid application of 'sizeof' to incomplete type` with `unique_ptr` pimpl | destructor generated where the type is incomplete | declare the destructor in the header, define it `= default` in the `.cpp` |
| `'xxx' is not a member of 'std'` after a compiler upgrade | relied on a transitive include | include the right header (`<cstdint>`, `<algorithm>`, ...) |

## 9. Review checklist

- [ ] Builds warning-free with the project's warning set on all supported compilers; tests pass under ASan+UBSan (and TSan for concurrent code).
- [ ] No naked `new`/`delete`/`malloc` ownership; RAII everywhere; rule of zero or complete rule of five.
- [ ] No dangling references, views, iterators; no use of moved-from objects.
- [ ] All untrusted sizes, indexes and integer arithmetic checked; no unsafe C string APIs; no user-controlled format strings.
- [ ] `const`, `explicit`, `override`, `noexcept` moves, `[[nodiscard]]` used consistently.
- [ ] CMake changes are target-based; no global flags; new dependencies via the project's package manager.
- [ ] Headers self-contained; no `using namespace` in headers; ABI considerations for public libraries.
- [ ] clang-tidy findings fixed or justified.

Full list: [review-checklist.md](review-checklist.md).

## 10. Frameworks

- **CMake, presets, vcpkg, Conan, FetchContent:** [cmake.md](cmake.md).
- **Qt:** `qt_add_executable`/`qt_standard_project_setup` with `AUTOMOC`; parent-child ownership (`new QWidget(parent)` is fine — the parent deletes it); never touch widgets off the GUI thread (signals/slots with queued connections).
- **Boost / Abseil / fmt / spdlog:** consume through imported targets; check which parts are already standard in your C++ version (`std::optional`, `std::variant`, `std::format`, `std::span`) before adding them.
- **Embedded / freestanding:** often no exceptions, RTTI or heap — check flags (`-fno-exceptions`) and keep to the project's allocator and coding standard (MISRA/AUTOSAR if required).

More library notes: [frameworks.md](frameworks.md).

Files in this skill

  • SKILL.md16.5 KB
  • build-errors.md10.1 KB
  • cmake.md7.2 KB
  • frameworks.md4.5 KB
  • review-checklist.md4.3 KB
  • undefined-behaviour.md7.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.