C++防御性編程策略
作者:程序員喵大人
優(yōu)先使用std::make_unique和std::make_shared,它們提供異常安全保證對(duì)于需要共享所有權(quán)的循環(huán)引用場(chǎng)景,使用std::weak_ptr打破循環(huán)自定義刪除器可用于管理非內(nèi)存資源(如文件句柄)。
內(nèi)存安全管理
智能指針的應(yīng)用
include <memory>
void safe_memory_management() {
// 獨(dú)占所有權(quán)場(chǎng)景
auto unique = std::make_unique<int>(42);
// 共享所有權(quán)場(chǎng)景
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);
}建議:
- 優(yōu)先使用std::make_unique和std::make_shared,它們提供異常安全保證
- 對(duì)于需要共享所有權(quán)的循環(huán)引用場(chǎng)景,使用std::weak_ptr打破循環(huán)
- 自定義刪除器可用于管理非內(nèi)存資源(如文件句柄)
容器與邊界安全
現(xiàn)代容器使用模式
include <vector>
include <array>
void container_safety() {
// 固定大小數(shù)組
std::array<int, 100> fixed_array;
// 動(dòng)態(tài)數(shù)組
std::vector<int> dynamic_array;
// 安全遍歷(C++11起)
for (auto& elem : dynamic_array) {
// 安全訪問(wèn)每個(gè)元素
}
// 安全訪問(wèn)方法
try {
int val = dynamic_array.at(42); // 邊界檢查
catch (const std::out_of_range& e) {
// 異常處理
}
}建議:
- 優(yōu)先使用標(biāo)準(zhǔn)庫(kù)容器而非原始數(shù)組
- 使用at()進(jìn)行邊界檢查訪問(wèn)
- C++20引入的std::span提供安全視圖訪問(wèn)
輸入驗(yàn)證策略
綜合驗(yàn)證方法
include <string>
include <regex>
include <charconv>
void validate_input(const std::string& input) {
// 空值檢查
if (input.empty()) {
throw std::invalid_argument("輸入不能為空");
}
// 正則驗(yàn)證
const std::regex name_pattern("^[\\w-]{3,50}$");
if (!std::regex_match(input, name_pattern)) {
throw std::invalid_argument("非法輸入格式");
}
// 數(shù)值轉(zhuǎn)換驗(yàn)證(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("數(shù)值轉(zhuǎn)換失敗");
}
}建議:
- 建立輸入驗(yàn)證的層次防御(前端+后端)
- 使用類型安全轉(zhuǎn)換而非C風(fēng)格轉(zhuǎn)換
字符串安全處理
現(xiàn)代字符串處理
include <string>
include <string_view>
void string_operations() {
// 安全構(gòu)造
std::string safe_str("可能包含危險(xiǎn)內(nèi)容", 0, 100); // 限制長(zhǎng)度
// 安全連接
std::string result = safe_str + "附加內(nèi)容";
// 安全視圖(C++17)
std::string_view view(safe_str);
// 格式化安全(C++20)
std::string formatted = std::format("安全格式: {}", safe_str);
// 避免緩沖區(qū)溢出
char buffer[100];
safe_str.copy(buffer, sizeof(buffer) - 1);
buffer[safe_str.copy(buffer, sizeof(buffer) - 1)] = '\0';
}建議:
- 禁用strcpy、sprintf等不安全C函數(shù)
- 使用std::string和std::string_view替代C風(fēng)格字符串
- 對(duì)于格式化,優(yōu)先使用C++20的std::format或第三方安全庫(kù)
異常安全設(shè)計(jì)
資源管理策略
include <memory>
include <fstream>
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;
// 允許移動(dòng)
ResourceHandler(ResourceHandler&&) = default;
ResourceHandler& operator=(ResourceHandler&&) = default;
};
void file_operation() {
std::ofstream file("data.txt");
if (!file) throw std::runtime_error("文件打開(kāi)失敗");
// RAII保證文件關(guān)閉
file << "安全寫入數(shù)據(jù)";
// 即使拋出異常,文件也會(huì)正確關(guān)閉
}建議:
- 遵循RAII(Resource Acquisition Is Initialization)原則
- 使用"獲取即初始化"模式管理資源
- 對(duì)于復(fù)雜操作,考慮事務(wù)模式或回滾機(jī)制
現(xiàn)在不少朋友都在準(zhǔn)備校招,常規(guī)的技術(shù)學(xué)習(xí)只是提高了代碼能力,還沒(méi)有提升從 0 到 1 整體做項(xiàng)目和解決問(wèn)題的能力!
責(zé)任編輯:武曉燕
來(lái)源:
程序員喵大人































