C++防御性编程策略

博主介绍:程序喵大人

最近新上线了一个网站(希加加职业发展平台),可以对简历进行评估、并且能够根据你的简历内容进行面试押题预测,分享给大家。各位有需要的同学也可以去网站上实践体验一下,希望能帮助到你~

下面正文开始⬇️

内存安全管理

智能指针的应用

cpp 复制代码
#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_uniquestd::make_shared,它们提供异常安全保证
  • 对于需要共享所有权的循环引用场景,使用 std::weak_ptr 打破循环
  • 自定义删除器可用于管理非内存资源(如文件句柄)

容器与边界安全

现代容器使用模式

cpp 复制代码
#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 提供安全视图访问

输入验证策略

综合验证方法

cpp 复制代码
#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 风格转换

字符串安全处理

现代字符串处理

cpp 复制代码
#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';
}

建议:

  • 禁用 strcpysprintf 等不安全 C 函数
  • 使用 std::stringstd::string_view 替代 C 风格字符串
  • 对于格式化,优先使用 C++20 的 std::format 或第三方安全库

异常安全设计

资源管理策略

cpp 复制代码
#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!