mcpField
M
modern-cpp

modern-cpp

github.com/trailofbits开发7.9k1.2k 次安装今天更新
代码仓库

关于 modern-cpp

modern-cpp 是一项面向安全的技能,用于编写、现代化改造和审查采用 C++20、C++23 与 C++26 惯用法的 C++ 代码。它结合更安全的编码模式与编译器加固指南,并按实际成熟度区分语言特性。

主要功能

  1. 01用现代 C++ 惯用法替换旧模式
  2. 02采用 C++20 和 C++23 语言特性
  3. 03应用编译器加固标志和 sanitizer
  4. 04审查 C++ 代码中的安全模式
  5. 05按成熟度评估 C++26 特性

适用场景

  1. 01编写安全关键的 C++ 代码
  2. 02现代化改造 C++20 之前的代码
  3. 03选择旧式或现代实现方式
  4. 04审查 C++ 惯用法的采用情况

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/trailofbits/skills --skill modern-cpp

安装后在 Claude Code 中输入/modern-cpp确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
anti-patterns.md
compiler-hardening.md
cpp20-features.md
cpp23-features.md
cpp26-features.md
safe-idioms.md

详细介绍

Modern C++

使用 C++20、C++23 和 C++26 惯用法编写现代 C++ 的指南。重点介绍可消除漏洞类别并减少样板代码的模式,并融入 Trail of Bits 的安全侧重点。

何时使用此技能

  • 编写新的 C++ 函数、类或库
  • 现代化现有 C++ 代码(C++20 之前的模式)
  • 在旧式方法和现代方法之间进行选择
  • 处理安全关键或安全敏感的 C++ 代码
  • 审查 C++ 代码是否采用了现代惯用法

何时不使用此技能

  • 用户明确要求使用较旧的标准:遵循约束(嵌入式、旧版 ABI)
  • 纯 C 代码:此技能仅适用于 C++
  • 构建系统问题:CMake、Meson、Bazel 配置不在范围内
  • 非 C++ 项目:C++ 并非主要语言的混合代码库

应避免的反模式

避免使用改用原因
new/deletestd::make_unique、std::make_shared消除内存泄漏和重复释放
原始拥有型指针std::unique_ptr、std::shared_ptrRAII 所有权语义
C 数组(int arr[N])std::array<int, N>可检查边界,具有值语义
指针 + 长度参数std::span<T>不拥有对象,可检查边界
printf / sprintfstd::format、std::print类型安全,不会发生缓冲区溢出
C 风格转换 (int)xstatic_cast<int>(x)意图明确,便于审计
#define 常量constexpr 变量具有作用域和类型,便于调试
SFINAE / enable_if概念 + requires约束和错误信息更易读
错误码 + 输出参数std::expected<T, E>可组合,错误处理类型安全
unionstd::variant类型安全,不会产生隐式未定义行为
原始 mutex.lock()/unlock()std::scoped_lock异常安全,不会死锁
std::threadstd::jthread自动汇合,支持停止令牌
assert() 宏contract_assert(C++26)工具可见,可配置
手动 CRTP推导 this(C++23)更简单,无模板样板代码
宏代码生成反射(C++26)零开销,可组合

完整表格(30 多种模式)请参阅 anti-patterns.md。

决策树

What are you doing?
|
+-- Writing new C++ code?
|   +-- Use modern idioms by default (C++20/23)
|   +-- Choose the newest standard your compiler supports
|   +-- See Feature Tiers below
|
+-- Modernizing existing code?
|   +-- Start with Tier 1 (C++20/23) replacements
|   +-- Prioritize by security impact (memory > types > style)
|   +-- See anti-patterns.md for the migration table
|
+-- Security-critical code?
|   +-- Enable compiler hardening flags (see below)
|   +-- Enable hardened libc++ mode
|   +-- Run sanitizers in CI
|   +-- See safe-idioms.md and compiler-hardening.md
|
+-- Using C++26 features?
    +-- Reflection: YES, plan for it (GCC 16+)
    +-- Contracts: cautiously, for new API boundaries
    +-- std::execution: wait for ecosystem maturity
    +-- See cpp26-features.md

特性分级

特性按当下的实际可用性分级,而非按标准版本分级。

第 1 级:现在即可使用(C++20/23,编译器支持成熟)
特性替代内容标准
概念 + requiresSFINAE、enable_ifC++20
范围 + 视图原始迭代器循环C++20
std::span<T>指针 + 长度C++20
std::formatsprintf、iostream 链式调用C++20
三路比较 <=>手动编写比较运算符C++20
std::jthreadstd::thread + 手动汇合C++20
指定初始化器按位置初始化结构体C++20
std::expected<T,E>错误码、边界处的异常C++23
std::print / std::printlnprintf、std::cout <<C++23
推导 thisCRTP、const/非 const 重复代码C++23
std::flat_map适用于读取密集型场景的 std::mapC++23
单子式 std::optional对 optional 进行嵌套 if 检查C++23

请参阅 cpp20-features.md 和 cpp23-features.md。

第 2 级:现在即可部署(无需升级标准)

这些方法可在不更改 C++ 标准版本的情况下提升安全性:

  • 编译器加固标志 — -D_FORTIFY_SOURCE=3、-fstack-protector-strong、-ftrivial-auto-var-init=zero
  • 加固版 libc++ — 使用 -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST,以约 0.3% 的开销进行边界检查
  • 在 CI 中使用消毒器 — 至少使用 ASan + UBSan;并发代码使用 TSan
  • 警告标志 — -Wall -Wextra -Wpedantic -Werror

请参阅 compiler-hardening.md。

第 3 级:规划采用(C++26,值得围绕其重构)

反射是 C++26 中最具变革性的单项特性。它消除了:

  • 序列化样板代码(一个通用函数即可替代每个结构体的 to_json)
  • 代码生成器(protobuf 代码生成、Qt MOC)
  • 基于宏的注册,以及枚举转字符串的变通方案

GCC 16(2026 年 4 月)已合并反射。规划新代码时应考虑借助这一特性。

第 4 级:持续关注(C++26,仍需成熟)
  • 契约(pre/post/contract_assert)——优于 assert(),但不支持虚函数,编译器支持也有限。谨慎地将其用于新的 API 边界。
  • std::execution(发送器/接收器)——功能强大的异步框架,但学习曲线陡峭、没有随附的调度器,文档也不完善。应等待生态系统成熟。

参见 cpp26-features.md。

编译器强化快速参考

必备标志(GCC + Clang)
-Wall -Wextra -Wpedantic -Werror
-D_FORTIFY_SOURCE=3
-fstack-protector-strong
-fstack-clash-protection
-ftrivial-auto-var-init=zero
-fPIE -pie
-Wl,-z,relro,-z,now
Clang 专用
-Wunsafe-buffer-usage
强化版 libc++(仅限 Clang/libc++)
-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST

Google 已在 Chrome 和其整个服务器集群中部署此方案:开销约为 0.3%,发现了 1000 多个漏洞,生产环境中的段错误减少了 30%。

完整指南请参见 compiler-hardening.md。

应当摒弃的自我安慰

自我安慰错误之处
“没有警告就能编译”警告取决于启用了哪些标志。添加 -Wall -Wextra -Wpedantic。
“ASan 在生产环境中太慢”使用 GWP-ASan 进行基于采样的生产环境检测(开销约为 0%)。
“我们只使用安全容器”迭代器失效和未经检查的 optional 访问仍可能被利用。
“智能指针更慢”与原始指针相比,std::unique_ptr 的开销为零。提出此说法前先测量。
“我们的代码没有内存漏洞”Google 启用强化版 libc++ 时发现了 1000 多个漏洞。其他团队也一样。
“C++26 特性还不可用”C++20/23 特性已经可用。强化标志适用于任何标准。从这些开始。
“现代 C++ 更难读”与通过 5 个输出参数检查错误码相比,std::expected 更易读。

最佳实践检查清单

  • 使用智能指针表示所有权,仅使用原始指针进行非拥有式观察
  • 函数参数优先使用 std::span,而非指针 + 长度
  • 对可能因类型化错误而失败的函数使用 std::expected
  • 使用概念约束模板,而非 SFINAE
  • 在所有构建中启用编译器强化标志和强化版 libc++
  • 在 CI 中运行 ASan + UBSan;并发代码还要添加 TSan
  • 尽可能使用 constexpr / consteval(从设计上避免未定义行为)
  • 忽略返回值可能导致错误时,为函数标记 [[nodiscard]]
  • 优先采用值语义;使用 std::variant 替代 union,使用 enum class 替代 enum
  • 在声明时初始化所有变量

接下来阅读

评论

支持 Markdown