C++安全需依托机制而非经验:禁用不安全C函数、用智能指针防悬空、检查整数溢出、RAII管理资源,并启用编译器保护与静态分析。

C++ 安全漏洞多源于内存失控、类型模糊和边界失察,不靠“经验”靠机制——用现代语言特性+静态检查+明确约定,才能真正堵住高危缺口。
缓冲区溢出:越界写入仍是头号杀手
数组下标不校验、red">gets、strcpy、sprintf 等 C 风格函数是经典雷区。C++ 中若用 raw pointer + 手动计算长度,同样危险。
- 禁用所有不带长度检查的 C 字符串函数,改用 std::string 或 std::array
- 用 std::vector::at() 替代 operator[](前者抛异常,后者不检查)
- 对输入长度做前置断言:if (len > buf.size()) throw std::length_error("input too long");
- 启用编译器保护:GCC/Clang 加 -fstack-protector-strong,MSVC 开启 /GS
悬空指针与 Use-After-Free
对象析构后仍被访问,或智能指针管理不当(如 get() 暴露裸指针又未严格管控生命周期),极易引发未定义行为。
- 优先使用 std::unique_ptr 和 std::shared_ptr,避免裸指针传递所有权
- 禁止长期保存 ptr.get() 返回的裸指针;若必须,加注释说明生命周期依赖关系
- 容器中存储智能指针而非对象本身,防止迭代器失效+析构导致的悬空
- 启用 AddressSanitizer(-fsanitize=address)在测试阶段捕获绝大多数 use-after-free
整数溢出与符号混淆
无符号整数下溢(0u - 1 → 极大正数)、有符号溢出(未定义行为)、size_t 与 int 混用(尤其循环变量),常导致逻辑绕过或越界访问。
立即学习“C++免费学习笔记(深入)”;
- 敏感计算前用 __builtin_add_overflow(GCC/Clang)或 std::add_overflow(C++23)做显式检查
- 循环索引统一用有符号类型(如 int),除非明确需要 >=2³¹ 的索引
- 接收用户输入的 size 参数,先转为 size_t 前验证非负且不过大(如 if (n 1024*1024) throw ...)
- 开启警告:-Wsign-conversion -Wconversion -Woverflow
RAII 失效与资源泄漏
忘记 close/fclose、释放失败未回滚、异常路径遗漏 cleanup,都会让文件句柄、内存、锁等资源持续泄漏,甚至引发拒绝服务。
- 所有资源封装进 RAII 类:文件用 std::fstream,锁用 std::lock_guard,自定义资源写专属 wrapper
- 构造函数中完成资源获取,失败则抛异常;析构函数确保释放(no-fail guarantee)
- 避免在析构函数中抛异常(会终止程序);释放失败可记录日志,但不 throw
- 用静态分析工具(如 Clang Static Analyzer、Cppcheck)扫描未关闭的 FILE* 或未 unlock 的 pthread_mutex_t
基本上就这些。C++ 的安全不是靠“小心”,而是把规则编进类型系统、编译流程和团队规范里。写得费点劲,但比半夜修 CVE 强得多。











