C++防御性编程策略
博主介绍:程序喵大人
- 35 - 资深C/C++/Rust/Android/iOS客户端开发
- 10年大厂工作经验
- 嵌入式/人工智能/自动驾驶/音视频/游戏开发入门级选手
- 《C++20高级编程》《C++23高级编程》等多本书籍著译者
- 更多原创精品文章,首发gzh,见文末
- 👇👇记得订阅专栏,以防走丢👇👇
😉C++基础系列专栏
😃C语言基础系列专栏
🤣C++大佬养成攻略专栏
🤓C++训练营
👉🏻个人网站
最近新上线了一个网站(希加加职业发展平台),可以对简历进行评估、并且能够根据你的简历内容进行面试押题预测,分享给大家。各位有需要的同学也可以去网站上实践体验一下,希望能帮助到你~
下面正文开始⬇️
内存安全管理
智能指针的应用
#include <memory>
#include <cstdio>void safe_memory_management() {// 独占所有权场景auto unique = std::make_unique<int>(42);// 共享所有权场景auto shared = std::make_shared<double>(3.14);// 弱引用观察者std::weak_ptr<double> observer = shared;// 自定义删除器auto file = std::unique_ptr<FILE, decltype(&fclose)>(fopen("data.txt", "r"), &fclose);
}
建议:
- 优先使用
std::make_unique
和std::make_shared
,它们提供异常安全保证 - 对于需要共享所有权的循环引用场景,使用
std::weak_ptr
打破循环 - 自定义删除器可用于管理非内存资源(如文件句柄)
容器与边界安全
现代容器使用模式
#include <vector>
#include <array>
#include <iostream>void container_safety() {// 固定大小数组std::array<int, 100> fixed_array;// 动态数组std::vector<int> dynamic_array;// 安全遍历(C++11起)for (auto& elem : dynamic_array) {// 安全访问每个元素}// 安全访问方法try {int val = dynamic_array.at(42); // 边界检查} catch (const std::out_of_range& e) {// 异常处理}
}
建议:
- 优先使用标准库容器而非原始数组
- 使用
at()
进行边界检查访问 - C++20 引入的
std::span
提供安全视图访问
输入验证策略
综合验证方法
#include <string>
#include <regex>
#include <charconv>
#include <stdexcept>
#include <iostream>void validate_input(const std::string& input) {// 空值检查if (input.empty()) {throw std::invalid_argument("输入不能为空");}// 正则验证const std::regex name_pattern("^[\\w-]{3,50}$");if (!std::regex_match(input, name_pattern)) {throw std::invalid_argument("非法输入格式");}// 数值转换验证(C++17)int value;auto [ptr, ec] = std::from_chars(input.data(), input.data() + input.size(), value);if (ec != std::errc()) {throw std::invalid_argument("数值转换失败");}
}
建议:
- 建立输入验证的层次防御(前端+后端)
- 使用类型安全转换而非 C 风格转换
字符串安全处理
现代字符串处理
#include <string>
#include <string_view>
#include <format>void string_operations() {// 安全构造std::string safe_str("可能包含危险内容", 0, 100); // 限制长度// 安全连接std::string result = safe_str + "附加内容";// 安全视图(C++17)std::string_view view(safe_str);// 格式化安全(C++20)std::string formatted = std::format("安全格式: {}", safe_str);// 避免缓冲区溢出char buffer[100];safe_str.copy(buffer, sizeof(buffer) - 1);buffer[safe_str.copy(buffer, sizeof(buffer) - 1)] = '\0';
}
建议:
- 禁用
strcpy
、sprintf
等不安全 C 函数 - 使用
std::string
和std::string_view
替代 C 风格字符串 - 对于格式化,优先使用 C++20 的
std::format
或第三方安全库
异常安全设计
资源管理策略
#include <memory>
#include <fstream>
#include <stdexcept>class Resource {};Resource* acquire_resource() { return new Resource(); }
void release_resource(Resource* res) { delete res; }class ResourceHandler {std::unique_ptr<Resource> resource;public:ResourceHandler() : resource(acquire_resource()) {}~ResourceHandler() {if (resource) release_resource(resource.get());}// 禁止拷贝ResourceHandler(const ResourceHandler&) = delete;ResourceHandler& operator=(const ResourceHandler&) = delete;// 允许移动ResourceHandler(ResourceHandler&&) = default;ResourceHandler& operator=(ResourceHandler&&) = default;
};void file_operation() {std::ofstream file("data.txt");if (!file) throw std::runtime_error("文件打开失败");// RAII保证文件关闭file << "安全写入数据";// 即使抛出异常,文件也会正确关闭
}
建议:
- 遵循 RAII (Resource Acquisition Is Initialization) 原则
- 使用“获取即初始化”模式管理资源
- 对于复杂操作,考虑事务模式或回滚机制
码字不易,欢迎大家点赞,关注,评论,谢谢!
👉 C++训练营
一个专为校招、社招3年工作经验的同学打造的 1v1 项目实战训练营,量身定制学习计划、每日代码review,简历优化,面试辅导,已帮助多名学员获得大厂offer!